GLConsumer.cpp revision b267579ba8dfe3f47d2a481c5a3c2254e3d565a1
18ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/*
28ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Copyright (C) 2010 The Android Open Source Project
38ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
48ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
58ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * you may not use this file except in compliance with the License.
68ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * You may obtain a copy of the License at
78ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
88ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
98ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Unless required by applicable law or agreed to in writing, software
118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * See the License for the specific language governing permissions and
148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * limitations under the License.
158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis */
168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define LOG_TAG "SurfaceTexture"
181c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis//#define LOG_NDEBUG 0
208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define GL_GLEXT_PROTOTYPES
228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define EGL_EGLEXT_PROTOTYPES
238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/egl.h>
258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/eglext.h>
268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2.h>
278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2ext.h>
288ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian#include <hardware/hardware.h>
307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3190ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/IGraphicBufferAlloc.h>
3290ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/ISurfaceComposer.h>
3390ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/SurfaceComposerClient.h>
3490ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/SurfaceTexture.h>
3541f673c9b3aac0d96e41c928845c39186d565212Mathias Agopian
3690ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <private/gui/ComposerService.h>
378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <utils/Log.h>
3968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian#include <utils/String8.h>
401c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#include <utils/Trace.h>
418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
4386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// to synchronize access to the buffers.  It will cause dequeueBuffer to stall,
4486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// waiting for the GL reads for the buffer being dequeued to complete before
4586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis// allowing the buffer to be dequeued.
4686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef USE_FENCE_SYNC
4786edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
4886edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
4986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
5086edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
5186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
52fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis// Macros for including the SurfaceTexture name in log messages
536807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
549d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
55a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
5632397c1cd3327905173b36baa6fd1c579bc328ffSteve Block#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
57e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5829b5762efc359022168e5099c1d17925444d3147Mathias Agopian
598ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisnamespace android {
608ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
61f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
62f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
63f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
64f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
65f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
66f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
67f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
68f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
69f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
70f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
71f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
72f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
73f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot180[16] = {
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 1, 0, 1,
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
92f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot270[16] = {
93f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
94f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
95f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
96f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
97f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
98f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
99f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
100f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
101eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam// Get an ID that's unique within this process.
102eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lamstatic int32_t createProcessUniqueId() {
103eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    static volatile int32_t globalCounter = 0;
104eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    return android_atomic_inc(&globalCounter);
105eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam}
106fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
107fb1b5a2f333800574b0da435d1200cf9b13d723fJamie GennisSurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
108b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
1091d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
1101d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
111b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
11286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#ifdef USE_FENCE_SYNC
11386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
11486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#else
11586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(false),
11686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis#endif
117eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
118eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mAbandoned(false),
119eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
1206b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
121eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    // Choose a name using the PID and a process-unique ID.
122eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
1236ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("SurfaceTexture");
124b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    if (bufferQueue == 0) {
125b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
126b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        ST_LOGV("Creating a new BufferQueue");
127b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        mBufferQueue = new BufferQueue(allowSynchronousMode);
128b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    }
129b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    else {
130b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        mBufferQueue = bufferQueue;
131b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    }
132b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(mName);
133b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
134fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
135fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
1368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisSurfaceTexture::~SurfaceTexture() {
1396ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("~SurfaceTexture");
140b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
141eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    abandon();
1428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1448072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatus_t SurfaceTexture::setBufferCountServer(int bufferCount) {
1458072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
146b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setBufferCountServer(bufferCount);
1478072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1488072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1498ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
150a5c75c01620179ce00812354778a29a80d76e71fMathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
151a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
152b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
153b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferSize(w, h);
154a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
155a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1568ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::updateTexImage() {
1571c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis    ATRACE_CALL();
1586ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("updateTexImage");
1598ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
1608ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
161e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    if (mAbandoned) {
162fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
1638e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian        return NO_INIT;
164e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian    }
165e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian
166b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    BufferQueue::BufferItem item;
167eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
16850c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // In asynchronous mode the list is guaranteed to be one buffer
16950c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis    // deep, while in synchronous mode we use the oldest buffer.
170b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    if (mBufferQueue->acquire(&item) == NO_ERROR) {
171eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        int buf = item.mBuf;
172eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        // This buffer was newly allocated, so we need to clean up on our side
173eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        if (item.mGraphicBuffer != NULL) {
174eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mGraphicBuffer = 0;
175eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
176eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                eglDestroyImageKHR(mEGLSlots[buf].mEglDisplay,
177eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                        mEGLSlots[buf].mEglImage);
178eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
179eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                mEGLSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
180eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            }
181eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
182eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        }
183b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
184f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        // Update the GL texture object.
185eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        EGLImageKHR image = mEGLSlots[buf].mEglImage;
18686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        EGLDisplay dpy = eglGetCurrentDisplay();
1878ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
188eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            if (item.mGraphicBuffer == 0) {
189fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis                ST_LOGE("buffer at slot %d is null", buf);
1908e19c2e97e11505ee2ecf336275fd956f2ccfa22Mathias Agopian                return BAD_VALUE;
191e47498f8f258967ff62d070f08ff2dadd4ae2b56Mathias Agopian            }
192eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            image = createImage(dpy, item.mGraphicBuffer);
193eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mEglImage = image;
194eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[buf].mEglDisplay = dpy;
1953cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            if (image == EGL_NO_IMAGE_KHR) {
1963cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // NOTE: if dpy was invalid, createImage() is guaranteed to
1973cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // fail. so we'd end up here.
1983cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                return -EINVAL;
1993cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            }
2008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2010eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
2020eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        GLint error;
2030eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
204fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
2050eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
2067a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
207fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
208fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
2097a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
2100eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        bool failed = false;
2110eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
212fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            ST_LOGE("error binding external texture image %p (slot %d): %#04x",
213b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian                    image, buf, error);
2140eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis            failed = true;
2150eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
2160eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        if (failed) {
217b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam            mBufferQueue->releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
218eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                    mEGLSlots[buf].mFence);
2198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            return -EINVAL;
2208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2219a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
222b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
22386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis            if (mUseFenceSync) {
22486edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
22586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                        NULL);
22686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                if (fence == EGL_NO_SYNC_KHR) {
227e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block                    ALOGE("updateTexImage: error creating fence: %#x",
22886edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                            eglGetError());
229b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam                    mBufferQueue->releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
230eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                            mEGLSlots[buf].mFence);
23186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                    return -EINVAL;
23286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                }
23386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                glFlush();
234eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                mEGLSlots[mCurrentTexture].mFence = fence;
23586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis            }
23686edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        }
23786edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
23886edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis        ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
23986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                mCurrentTexture,
24086edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis                mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
241eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0);
2426ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis
243eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        // release old buffer
244b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        mBufferQueue->releaseBuffer(mCurrentTexture,
245eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                mEGLSlots[mCurrentTexture].mEglDisplay,
246eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                mEGLSlots[mCurrentTexture].mFence);
247b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
2489a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        // Update the SurfaceTexture state.
249b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian        mCurrentTexture = buf;
250eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
251eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentCrop = item.mCrop;
252eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTransform = item.mTransform;
253eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentScalingMode = item.mScalingMode;
254eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mCurrentTimestamp = item.mTimestamp;
255736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis        computeCurrentTransformMatrix();
25650c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
25750c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis        // Now that we've passed the point at which failures can happen,
25850c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis        // it's safe to remove the buffer from the front of the queue.
259eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
2607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    } else {
2617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        // We always bind the texture even if we don't update its contents.
262fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis        glBindTexture(mTexTarget, mTexName);
2638ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
26450c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
2658ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2668ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2678ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2687a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
2697a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
2707a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
2717a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
2727a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
2737a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
2747a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
2757a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
2767a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
2777a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
2787a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
2797a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
2807a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
2817a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
2827a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
2837a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
2847a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
2857a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
2867a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
2877a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
288fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
2897a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
2907a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
291f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
292f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
293736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
294736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
295736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
296736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennisvoid SurfaceTexture::computeCurrentTransformMatrix() {
2976ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("computeCurrentTransformMatrix");
298f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
299a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
300a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
301a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
302a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
303a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
304a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
305a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
306a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
307a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
308a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
309a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
310a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
311a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
312a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
313a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
314a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
315a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
316a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
317a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
318a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
319a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
320a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
321a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
322a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
323f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
324f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
325eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
326a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float tx, ty, sx, sy;
327a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (!mCurrentCrop.isEmpty()) {
328d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // In order to prevent bilinear sampling at the of the crop rectangle we
329d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // may need to shrink it by 2 texels in each direction.  Normally this
330d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // would just need to take 1/2 a texel off each end, but because the
331d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // chroma channels will likely be subsampled we need to chop off a whole
332d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // texel.  This will cause artifacts if someone does nearest sampling
333d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
334d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // accomodate the bilinear and nearest sampling uses.
335d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        //
336d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // If nearest sampling turns out to be a desirable usage of these
337d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // textures then we could add the ability to switch a SurfaceTexture to
338d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // nearest-mode.  Preferably, however, the image producers (video
339d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // decoder, camera, etc.) would simply not use a crop rectangle (or at
340d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // least not tell the framework about it) so that the GPU can do the
341d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // correct edge behavior.
342d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        int xshrink = 0, yshrink = 0;
343d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.left > 0) {
344d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
345d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
346d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
347d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = 0.0f;
348d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
349a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
350d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
351d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
352a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
353d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
354d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    float(buf->getHeight());
355d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
356d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
357d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = 0.0f;
358d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
359d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.top > 0) {
360d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
361d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
362d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
363d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
364a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    } else {
365a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        tx = 0.0f;
366a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        ty = 0.0f;
367a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx = 1.0f;
368a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sy = 1.0f;
369a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
370f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
371a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
372a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
373f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
374d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
375f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
376f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
377a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
378a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
379a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
380a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
381a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
382a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
383a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
384736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
385f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
386f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
3871d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
3886ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
3891d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
3901d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
3911d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
3921d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
393c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennisvoid SurfaceTexture::setFrameAvailableListener(
394292a31a4c2ae2f6faf134e8e4a726583017dad06Pannag Sanketi        const sp<FrameAvailableListener>& listener) {
3956ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("setFrameAvailableListener");
396c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    Mutex::Autolock lock(mMutex);
397b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setFrameAvailableListener(listener);
398c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis}
399c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis
4008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
4018ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
4028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
4038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
4048ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
4058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
4068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
4078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
4088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
4093cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
4103cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
411fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
4128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
4138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
4148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
4158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4167a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
4177a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
4187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
4197a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
4207a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
4217a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
4227a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
4237a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentCrop;
4247a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
4257a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
4267a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
4277a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
4287a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
4297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
4307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
4317734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopianuint32_t SurfaceTexture::getCurrentScalingMode() const {
4327734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
4337734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
4347734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
4357734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
43659769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennisbool SurfaceTexture::isSynchronousMode() const {
43759769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    Mutex::Autolock lock(mMutex);
438b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->isSynchronousMode();
43959769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis}
44059769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
4417b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisvoid SurfaceTexture::abandon() {
4427b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    Mutex::Autolock lock(mMutex);
4437b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis    mAbandoned = true;
44497a9884edcc6fbb311386ecfcd6e3045437f0df0Mathias Agopian    mCurrentTextureBuf.clear();
445eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
446eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    // destroy all egl buffers
447b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
448eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        mEGLSlots[i].mGraphicBuffer = 0;
449eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        if (mEGLSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
450eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            eglDestroyImageKHR(mEGLSlots[i].mEglDisplay,
451eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam                    mEGLSlots[i].mEglImage);
452eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
453eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mEGLSlots[i].mEglDisplay = EGL_NO_DISPLAY;
454eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam        }
455eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    }
456eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
457eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    // disconnect from the BufferQueue
458b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->consumerDisconnect();
4597b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
4607b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
461fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennisvoid SurfaceTexture::setName(const String8& name) {
462eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
463fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
464b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(name);
465b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
466b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
467b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
468b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
469b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
470b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
471b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
472b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
473b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
474b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setConsumerUsageBits(usage);
475b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
476b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
477b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setTransformHint(uint32_t hint) {
478b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
479b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setTransformHint(hint);
480b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
481b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
482b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring BufferQueue from SurfaceTexture
483b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Should not be in final interface once users of SurfaceTexture are clean up.
484b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setSynchronousMode(bool enabled) {
485b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
486b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setSynchronousMode(enabled);
487b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
488b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
489b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring, should not be in final interface
490b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamsp<BufferQueue> SurfaceTexture::getBufferQueue() const {
491b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
492b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue;
493b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
494b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
495b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring, should not be in final interface
496b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::setBufferCount(int bufferCount) {
497b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
498b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setBufferCount(bufferCount);
499b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
500b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
501b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam// Used for refactoring, should not be in final interface
502b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lamstatus_t SurfaceTexture::connect(int api,
503b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam                uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
504b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
505b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->connect(api, outWidth, outHeight, outTransform);
506fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis}
507fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
50868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopianvoid SurfaceTexture::dump(String8& result) const
50968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
51068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    char buffer[1024];
51168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    dump(result, "", buffer, 1024);
51268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
51368c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
51468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopianvoid SurfaceTexture::dump(String8& result, const char* prefix,
51568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian        char* buffer, size_t SIZE) const
51668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
51768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    Mutex::Autolock _l(mMutex);
518eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    snprintf(buffer, SIZE, "%smTexName=%d\n", prefix, mTexName);
51968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
52068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
52168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    snprintf(buffer, SIZE,
522eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
523eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            ,prefix, mCurrentCrop.left,
52468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian            mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
525eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam            mCurrentTransform, mCurrentTexture
52668c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    );
52768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian    result.append(buffer);
52868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
529eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
530b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->dump(result, prefix, buffer, SIZE);
53168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
53268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
533f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
534f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
535f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
536f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
537f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
538f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
539f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
540f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
541f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
542f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
543f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
544f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
545f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
546f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
547f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
548f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
549f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
550f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
551f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
552f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
553f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
554f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
5558ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
556