GLConsumer.cpp revision 9fea3421ffddf6480f57f55a25936a886043d909
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
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
101fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
102fb1b5a2f333800574b0da435d1200cf9b13d723fJamie GennisSurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
103b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
1049fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),
1051d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
1061d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
1075c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
108b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
10986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef USE_FENCE_SYNC
11086edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
11186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#else
11286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(false),
11386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
114eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
115ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
116ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
11774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
11874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1196b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
1206ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("SurfaceTexture");
121b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
122fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
123fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
124fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
1259fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1288072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatus_t SurfaceTexture::setBufferCountServer(int bufferCount) {
1298072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
130b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setBufferCountServer(bufferCount);
1318072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1328072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1338ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
134a5c75c01620179ce00812354778a29a80d76e71fMathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
135a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
136b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
137016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
138016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
139b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferSize(w, h);
140a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
141a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::updateTexImage() {
1432c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian    return SurfaceTexture::updateTexImage(NULL);
1442c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
1452c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
1469fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisstatus_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) {
1479fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    status_t err = ConsumerBase::acquireBufferLocked(item);
1489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
1499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
1509fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1519fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1529fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    int slot = item->mBuf;
1539fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (item->mGraphicBuffer != NULL) {
1549fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
1559fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage);
1569fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
1579fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
1589fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1599fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1609fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    // Update the GL texture object. We may have to do this even when
1619fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
1629fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    // detaching from a context but the buffer has not been re-allocated.
1639fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (mEglSlots[slot].mEglImage == EGL_NO_IMAGE_KHR) {
1649fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR image = createImage(mEglDisplay, mSlots[slot].mGraphicBuffer);
1659fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
1669fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            return UNKNOWN_ERROR;
1679fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
1689fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        mEglSlots[slot].mEglImage = image;
1699fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1709fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1719fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
1729fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
1739fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1749fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisstatus_t SurfaceTexture::releaseBufferLocked(int buf, EGLDisplay display,
1759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       EGLSyncKHR eglFence, const sp<Fence>& fence) {
1769fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    status_t err = ConsumerBase::releaseBufferLocked(buf, mEglDisplay,
1779fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis           eglFence, fence);
1789fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1799fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[mCurrentTexture].mEglFence = EGL_NO_SYNC_KHR;
1809fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1819fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
1829fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
1839fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1842c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopianstatus_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
1851c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis    ATRACE_CALL();
1866ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("updateTexImage");
1878ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
1888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1899abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
1909abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
191e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    if (mAbandoned) {
19274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("updateTexImage: SurfaceTexture is abandoned!");
1938e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        return NO_INIT;
194e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    }
195e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian
19674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
19774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("updateTexImage: SurfaceTexture is not attached to an OpenGL "
19874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
19974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
20074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
20174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
202ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
203ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
204ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
20574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
20674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            dpy == EGL_NO_DISPLAY) {
207ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis        ST_LOGE("updateTexImage: invalid current EGLDisplay");
20874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
209ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
210ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
21174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
21274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ctx == EGL_NO_CONTEXT) {
213ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis        ST_LOGE("updateTexImage: invalid current EGLContext");
21474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
215ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
216ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
217ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay = dpy;
218ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext = ctx;
219ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
220b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    BufferQueue::BufferItem item;
221eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
22250c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // In asynchronous mode the list is guaranteed to be one buffer
22350c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // deep, while in synchronous mode we use the oldest buffer.
2249fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    err = acquireBufferLocked(&item);
225fbcda930dd8b2823cfeb160fd0131f5897b7522fDaniel Lam    if (err == NO_ERROR) {
226eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        int buf = item.mBuf;
227b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
2282c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        // we call the rejecter here, in case the caller has a reason to
2292c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        // not accept this buffer. this is used by SurfaceFlinger to
2302c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        // reject buffers which have the wrong size
2319fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
2329fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);
2332c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian            glBindTexture(mTexTarget, mTexName);
2342c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian            return NO_ERROR;
2352c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
2362c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
2379fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        GLint error;
2389fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
2399fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
2408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2410eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
2429fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR image = mEglSlots[buf].mEglImage;
2439fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glBindTexture(mTexTarget, mTexName);
2449fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
24574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
2469fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
2479fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            ST_LOGE("updateTexImage: error binding external texture image %p "
2489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    "(slot %d): %#04x", image, buf, error);
2499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            err = UNKNOWN_ERROR;
2509fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
251ce7a6c0fc9d75b80da030d1790321e84475f956aJamie Gennis
2529fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (err == NO_ERROR) {
2539fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            err = syncForReleaseLocked(dpy);
2548ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2559a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
2567e477bfe11f8bb31622353b64e85721df3cf9702Mathias Agopian        if (err != NO_ERROR) {
25774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // Release the buffer we just acquired.  It's not safe to
25874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // release the old buffer, so instead we just drop the new frame.
2599fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);
26074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
26186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        }
26286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
26386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
26486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                mCurrentTexture,
26586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
2669fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                buf, mSlots[buf].mGraphicBuffer->handle);
2676ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis
2689abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        // release old buffer
26974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
2709fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            status_t status = releaseBufferLocked(mCurrentTexture, dpy,
2719fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    mEglSlots[mCurrentTexture].mEglFence,
2729fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    mSlots[mCurrentTexture].mFence);
2739fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
2749fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                ST_LOGE("updateTexImage: failed to release buffer: %s (%d)",
2759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                       strerror(-status), status);
2769abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam                err = status;
2779abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam            }
27874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
279b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
2809a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        // Update the SurfaceTexture state.
281b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mCurrentTexture = buf;
2829fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
283eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentCrop = item.mCrop;
284eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTransform = item.mTransform;
285eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentScalingMode = item.mScalingMode;
286eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTimestamp = item.mTimestamp;
287dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall        mCurrentFence = item.mFence;
288736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis        computeCurrentTransformMatrix();
289fbcda930dd8b2823cfeb160fd0131f5897b7522fDaniel Lam    } else  {
290fbcda930dd8b2823cfeb160fd0131f5897b7522fDaniel Lam        if (err < 0) {
29145cb2ba1d52d81e20702b62610422fb09aaedeaeJamie Gennis            ST_LOGE("updateTexImage failed on acquire %d", err);
292fbcda930dd8b2823cfeb160fd0131f5897b7522fDaniel Lam        }
2937a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        // We always bind the texture even if we don't update its contents.
294fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
295fbcda930dd8b2823cfeb160fd0131f5897b7522fDaniel Lam        return OK;
2968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
29750c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
2989abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    return err;
2998ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
3008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
301ef19414bd8b77a26f5751f3845be79025a8263feJesse Hallvoid SurfaceTexture::setReleaseFence(int fenceFd) {
3023d1d09c0c116c42f7d083f87628b5f8377b1f275Jamie Gennis    sp<Fence> fence(new Fence(fenceFd));
30345cb2ba1d52d81e20702b62610422fb09aaedeaeJamie Gennis    if (fenceFd == -1 || mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)
304ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall        return;
3059fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (!mSlots[mCurrentTexture].mFence.get()) {
3069fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        mSlots[mCurrentTexture].mFence = fence;
307ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    } else {
308ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall        sp<Fence> mergedFence = Fence::merge(
309ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall                String8("SurfaceTexture merged release"),
3109fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                mSlots[mCurrentTexture].mFence, fence);
311e7db724bed5d1e5086801df7705d9b1f2a071785Jesse Hall        if (!mergedFence.get()) {
31245cb2ba1d52d81e20702b62610422fb09aaedeaeJamie Gennis            ST_LOGE("failed to merge release fences");
313ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall            // synchronization is broken, the best we can do is hope fences
314ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall            // signal in order so the new fence will act like a union
3159fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mSlots[mCurrentTexture].mFence = fence;
316e7db724bed5d1e5086801df7705d9b1f2a071785Jesse Hall            return;
317ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall        }
3189fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        mSlots[mCurrentTexture].mFence = mergedFence;
319ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
320ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
321ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
32274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::detachFromContext() {
32374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
32474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
32574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
32674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
32774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
32874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: abandoned SurfaceTexture");
32974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
33074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
33174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
33274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
33374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: SurfaceTexture is not attached to a "
33474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
33574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
33674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
33774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
33874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
33974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
34074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
34174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
34274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
34374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
34474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
34574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
34674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
34774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
34874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
34974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
35074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
35274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
35374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
35474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
35574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
35674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
35874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
35974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3609aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // Because we're giving up the EGLDisplay we need to free all the EGLImages
3619aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // that are associated with it.  They'll be recreated when the
3629aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a
3639aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // new EGLDisplay).
3649aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
3659fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR img = mEglSlots[i].mEglImage;
3665c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
3679aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
3689fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
3699aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        }
3709aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    }
3719aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis
37274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
37374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
37474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
37574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
37774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
37874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::attachToContext(GLuint tex) {
38074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
38174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
38274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
38374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
38474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
38574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: abandoned SurfaceTexture");
38674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
38774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
38874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
38974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
39074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: SurfaceTexture is already attached to a "
39174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
39274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
39374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
39474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
39674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
39774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
39974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
40074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
40174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
40274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
40474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
40574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
40674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
40774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
40974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
41074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    glBindTexture(mTexTarget, tex);
41174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
4135c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // The EGLImageKHR that was associated with the slot was destroyed when
4145c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // the SurfaceTexture was detached from the old context, so we need to
4155c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // recreate it here.
4165c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
4175c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
4185c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis            return UNKNOWN_ERROR;
41974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
42074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // Attach the current buffer to the GL texture.
42274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
42374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        GLint error;
42574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = OK;
42674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
42774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ST_LOGE("attachToContext: error binding external texture image %p "
42874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                    "(slot %d): %#04x", image, mCurrentTexture, error);
42974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            err = UNKNOWN_ERROR;
43074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
43174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4325c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // We destroy the EGLImageKHR here because the current buffer may no
4335c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // longer be associated with one of the buffer slots, so we have
4345c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // nowhere to to store it.  If the buffer is still associated with a
4355c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // slot then another EGLImageKHR will be created next time that buffer
4365c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // gets acquired in updateTexImage.
4375c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        eglDestroyImageKHR(dpy, image);
43874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
43974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
44074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
44174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
44274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
44374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
44574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
44674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
44774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
44874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
45074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
45174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennisstatus_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
45374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
45474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
4569fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
45774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (fence != EGL_NO_SYNC_KHR) {
45874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // There is already a fence for the current slot.  We need to wait
45974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // on that before replacing it with another fence to ensure that all
46074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // outstanding buffer accesses have completed before the producer
46174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            // accesses it.
46274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
46374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            if (result == EGL_FALSE) {
46474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                ST_LOGE("syncForReleaseLocked: error waiting for previous "
46574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                        "fence: %#x", eglGetError());
46674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
46774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
46874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
46974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                        "fence");
47074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return TIMED_OUT;
47174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
47274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            eglDestroySyncKHR(dpy, fence);
47374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
47474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
47574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // Create a fence for the outstanding accesses in the current OpenGL ES
47674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        // context.
47774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
47874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (fence == EGL_NO_SYNC_KHR) {
47974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
48074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                    eglGetError());
48174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return UNKNOWN_ERROR;
48274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
48374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glFlush();
4849fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        mEglSlots[mCurrentTexture].mEglFence = fence;
48574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
48674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
48774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
48874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
48974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4907a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
4917a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
4927a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
4937a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
4947a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
4957a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
4967a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
4977a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
4987a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
4997a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5007a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
5017a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5027a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
5037a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
5047a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5057a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5067a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
5077a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5087a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5097a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
510fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
5117a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5127a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
513f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
514f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
515736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
516736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
517736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
5185c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennisvoid SurfaceTexture::setFilteringEnabled(bool enabled) {
5195c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
5205c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
5215c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
5225c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    if (needsRecompute) {
5235c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        computeCurrentTransformMatrix();
5245c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
5255c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
5265c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
527736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennisvoid SurfaceTexture::computeCurrentTransformMatrix() {
5286ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("computeCurrentTransformMatrix");
529f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
530a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
531a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
532a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
533a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
534a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
535a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
536a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
537a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
538a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
539a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
540a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
541a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
542a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
543a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
544a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
545a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
546a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
547a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
548a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
549a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
550a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
551a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
552a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
553a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
554f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
555f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
556eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
557d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    Rect cropRect = mCurrentCrop;
5585c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
5595c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferWidth = buf->getWidth();
5605c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferHeight = buf->getHeight();
561d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    if (!cropRect.isEmpty()) {
5625c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        float shrinkAmount = 0.0f;
5635c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (mFilteringEnabled) {
5645c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // In order to prevent bilinear sampling beyond the edge of the
5655c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // crop rectangle we may need to shrink it by 2 texels in each
5665c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // dimension.  Normally this would just need to take 1/2 a texel
5675c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // off each end, but because the chroma channels of YUV420 images
5685c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // are subsampled we may need to shrink the crop region by a whole
5695c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // texel on each side.
5705c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            switch (buf->getPixelFormat()) {
5715c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_8888:
5725c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBX_8888:
5735c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_888:
5745c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_565:
5755c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_BGRA_8888:
5765c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_5551:
5775c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_4444:
5785c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // We know there's no subsampling of any channels, so we
5795c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // only need to shrink by a half a pixel.
5805c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 0.5;
5814f9c284de4b9159126f69eb1219c410f66cc872cRomain Guy                    break;
5829fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
5835c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                default:
5845c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // If we don't recognize the format, we must assume the
5855c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // worst case (that we care about), which is YUV420.
5865c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 1.0;
5879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    break;
5885c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
5895c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
5905c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
5915c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        // Only shrink the dimensions that are not the size of the buffer.
5925c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.width() < bufferWidth) {
5935c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
5945c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
5955c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferWidth;
5965c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
5975c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.height() < bufferHeight) {
5985c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
5995c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
6005c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
6015c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
6025c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
603a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
604f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
605a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
606a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
607f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
608d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
609f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
610f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
611a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
612a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
613a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
614a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
615a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
616a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
617a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
618736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
619f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
620f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
6211d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
6226ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
6231d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
6241d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
6251d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
6261d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
6278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
6288ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
6298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
6308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
6318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
6328ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
6338ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
6348ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
6358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
6363cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
6373cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
638fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
6398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
6408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
6418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
6428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
6437a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
6447a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
6457a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
6467a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6487a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
6497a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
650016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
651016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
652016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
653016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newWidth = mCurrentCrop.width();
654016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newHeight = mCurrentCrop.height();
655016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
656016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
657016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
658016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too wide: newWidth = %d", newWidth);
659016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
660016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
661016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too tall: newHeight = %d", newHeight);
662016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
663016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
664016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
665016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth < mCurrentCrop.width()) {
666016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dw = (newWidth - mCurrentCrop.width())/2;
667016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
668016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
669016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
670016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newHeight < mCurrentCrop.height()) {
671016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dh = (newHeight - mCurrentCrop.height())/2;
672016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
673016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
674016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
675016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
676016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
677016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
678016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
679016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
680016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
681016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
6827a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6837a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6847a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
6857a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
6867a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
6877a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6887a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6897734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopianuint32_t SurfaceTexture::getCurrentScalingMode() const {
6907734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
6917734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
6927734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
6937734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
694dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hallsp<Fence> SurfaceTexture::getCurrentFence() const {
695dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
696dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
697dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
698dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
69959769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennisbool SurfaceTexture::isSynchronousMode() const {
70059769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    Mutex::Autolock lock(mMutex);
701b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->isSynchronousMode();
70259769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis}
70359769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
704fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennisvoid SurfaceTexture::freeBufferLocked(int slotIndex) {
705fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
7069abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
7079abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
7089abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
7099fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
7109aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    if (img != EGL_NO_IMAGE_KHR) {
7119aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
7129aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        eglDestroyImageKHR(mEglDisplay, img);
713fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
7149fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
7159fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
716fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
717fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
7189fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisvoid SurfaceTexture::abandonLocked() {
7199fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ST_LOGV("abandonLocked");
7209fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mCurrentTextureBuf.clear();
7219fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
7227b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
7237b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
724fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennisvoid SurfaceTexture::setName(const String8& name) {
725eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
726fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
727b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(name);
728b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
729b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
730b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
731b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
732b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
733b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
734b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
735b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
736b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
73785b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
738b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setConsumerUsageBits(usage);
739b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
740b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
741b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setTransformHint(uint32_t hint) {
742b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
743b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setTransformHint(hint);
744b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
745b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
746b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring BufferQueue from SurfaceTexture
747b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Should not be in final interface once users of SurfaceTexture are clean up.
748b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setSynchronousMode(bool enabled) {
749b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
750b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setSynchronousMode(enabled);
751b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
752b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
7539fea3421ffddf6480f57f55a25936a886043d909Jamie Gennisvoid SurfaceTexture::dumpLocked(String8& result, const char* prefix,
7549fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        char* buffer, size_t size) const
75568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
7569fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    snprintf(buffer, size,
7579fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
7589fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
7599fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
7609fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
7619fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
76268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
76368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
7649fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::dumpLocked(result, prefix, buffer, size);
76568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
76668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
767f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
768f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
769f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
770f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
771f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
772f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
773f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
774f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
775f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
776f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
777f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
778f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
779f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
780f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
781f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
782f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
783f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
784f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
785f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
786f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
787f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
788f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
7898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
790