GLConsumer.cpp revision 74d211ae26a0257c6075a823812e40b55aa1e653
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
172adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden#define LOG_TAG "GLConsumer"
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
31ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian#include <gui/GLConsumer.h>
3290ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/IGraphicBufferAlloc.h>
3390ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/ISurfaceComposer.h>
3490ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/SurfaceComposerClient.h>
3541f673c9b3aac0d96e41c928845c39186d565212Mathias Agopian
3690ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <private/gui/ComposerService.h>
37ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian#include <private/gui/SyncFeatures.h>
388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <utils/Log.h>
4068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian#include <utils/String8.h>
411c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#include <utils/Trace.h>
428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4397eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddennamespace android {
4497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
452adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden// Macros for including the GLConsumer name in log messages
466807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
479d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
48a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
4932397c1cd3327905173b36baa6fd1c579bc328ffSteve Block#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
50e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5129b5762efc359022168e5099c1d17925444d3147Mathias Agopian
52f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
53f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
54f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
55f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
56f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
57f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
58f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
59f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
60f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
61f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
62f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
63f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
64f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
65f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
66f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
67f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
68f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
69f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
70f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
71f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
72f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
73f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
80fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
812adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenGLConsumer::GLConsumer(GLuint tex, bool allowSynchronousMode,
82b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
839fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),
841d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
851df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    mCurrentFence(Fence::NO_FENCE),
861d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
875c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
88b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
8986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
90eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
91ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
92ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
9374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
9474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
956b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
962adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    ST_LOGV("GLConsumer");
97b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
98fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
99fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
100fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
1019fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1042adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
1058072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
10631a353da225af5329735451c761b430d82dfda1bJamie Gennis    return mBufferQueue->setDefaultMaxBufferCount(bufferCount);
1078072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1088072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1102adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
111a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
112b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
113016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
114016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
115b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferSize(w, h);
116a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
117a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1182adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::updateTexImage() {
119bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
120bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("updateTexImage");
121bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
122bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
123bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
1242adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("updateTexImage: GLConsumer is abandoned!");
125bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
126bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
127bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
128bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
129bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
130bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
131bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
132bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
133bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
134bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    BufferQueue::BufferItem item;
135bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
136bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
137bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
138bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
139bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = acquireBufferLocked(&item);
140bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
141bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
142bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
143bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGV("updateTexImage: no buffers were available");
144bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
145bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
146bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
147bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("updateTexImage: acquire failed: %s (%d)",
148bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
149bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
150bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
151bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
152bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
153bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
154bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = releaseAndUpdateLocked(item);
155bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
156bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
157bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
158bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
159bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
160bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
16197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
16297eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
1632c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
1642c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
1652adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item) {
1669fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    status_t err = ConsumerBase::acquireBufferLocked(item);
1679fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
1689fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
1699fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1709fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1719fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    int slot = item->mBuf;
1729fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (item->mGraphicBuffer != NULL) {
173bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // This buffer has not been acquired before, so we must assume
174bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // that any EGLImage in mEglSlots is stale.
1759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
176bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
177bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
178bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                      slot);
179bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                // keep going
180bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            }
1819fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
1829fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
1839fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1849fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1859fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
1869fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
1879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1882adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::releaseBufferLocked(int buf, EGLDisplay display,
189b27254154642575dfb4bbfa79fbedde7d7ee23ddJamie Gennis       EGLSyncKHR eglFence) {
190bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = ConsumerBase::releaseBufferLocked(buf, display, eglFence);
1919fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
192d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
1939fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1949fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
1959fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
1969fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1972adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item)
198bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
1999abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
2009abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
20174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
2022adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("releaseAndUpdate: GLConsumer is not attached to an OpenGL "
20374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
20474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
20574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
20674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
207bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
208bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
209bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
210bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
211ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
212ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
213bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    int buf = item.mBuf;
214bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
215bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // If the mEglSlot entry is empty, create an EGLImage for the gralloc
216bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // buffer currently in the slot in ConsumerBase.
217bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    //
218bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
219bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // means the buffer was previously acquired), if we destroyed the
220bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // EGLImage when detaching from a context but the buffer has not been
221bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // re-allocated.
222bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
223bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer);
224bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (image == EGL_NO_IMAGE_KHR) {
225bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGW("releaseAndUpdate: unable to createImage on display=%p slot=%d",
226bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                  mEglDisplay, buf);
227bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
228bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
229bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        mEglSlots[buf].mEglImage = image;
230ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
231ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
232bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
233bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = syncForReleaseLocked(mEglDisplay);
234bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
235bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // Release the buffer we just acquired.  It's not safe to
236bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // release the old buffer, so instead we just drop the new frame.
237bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        releaseBufferLocked(buf, mEglDisplay, EGL_NO_SYNC_KHR);
238bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
239bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
240ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
241bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("releaseAndUpdate: (slot=%d buf=%p) -> (slot=%d buf=%p)",
242bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture,
243bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
244bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            buf, mSlots[buf].mGraphicBuffer->handle);
245eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
246bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
247bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
248bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t status = releaseBufferLocked(mCurrentTexture, mEglDisplay,
249bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                mEglSlots[mCurrentTexture].mEglFence);
250bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
251bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)",
252bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                   strerror(-status), status);
253bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = status;
254bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // keep going, with error raised [?]
2552c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
256bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
2572c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
2582adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // Update the GLConsumer state.
259bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTexture = buf;
260bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
261bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
262bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
263bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
264bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
265bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
266bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
267bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
268bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
269bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
270bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
271bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
2722adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindTextureImageLocked() {
273bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
274bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
275bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
276bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
277bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
278bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
279bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
280bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
281bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
282bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
283bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
284bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
285bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (mCurrentTextureBuf == NULL) {
286bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: no currently-bound texture");
287bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return NO_INIT;
2888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
28997eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        status_t err = bindUnslottedBufferLocked(mEglDisplay);
29097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        if (err != NO_ERROR) {
29197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden            return err;
29297eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        }
293bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    } else {
294bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
2950eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
2969fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
29774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
2989fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
299bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: error binding external texture image %p"
300bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                    ": %#04x", image, error);
301bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
3028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
303bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
30497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
30597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
30697eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
30797eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
308bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
3099a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
3102adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::checkAndUpdateEglStateLocked() {
311bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
312bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
31386edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
314bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
315bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            dpy == EGL_NO_DISPLAY) {
316bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
317bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
318bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
319b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
320bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
321bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ctx == EGL_NO_CONTEXT) {
322bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
323bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
3248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
32550c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
326bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
327bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
328bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
3298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
3308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
33113f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hallvoid GLConsumer::setReleaseFence(const sp<Fence>& fence) {
33213f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall    if (fence->isValid() &&
33313f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
33413f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        status_t err = addReleaseFence(mCurrentTexture, fence);
33513f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        if (err != OK) {
33613f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
33713f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall                    strerror(-err), err);
33813f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        }
339ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
340ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
341ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
3422adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::detachFromContext() {
34374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
34474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
34574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
34674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
34774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
3482adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: abandoned GLConsumer");
34974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
35074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
35174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
3532adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: GLConsumer is not attached to a "
35474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
35574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
35674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
35774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
35874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
35974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
36074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
36174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
36274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
36374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
36474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
36574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
36674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
36774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
36874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
36974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
37074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
37274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
37374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
37474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
37574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
37674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
37874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
37974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3809aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // Because we're giving up the EGLDisplay we need to free all the EGLImages
3819aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // that are associated with it.  They'll be recreated when the
3822adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // GLConsumer gets attached to a new OpenGL ES context (and thus gets a
3839aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // new EGLDisplay).
3849aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
3859fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR img = mEglSlots[i].mEglImage;
3865c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
3879aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
3889fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
3899aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        }
3909aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    }
3919aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis
39274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
39374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
39474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
39574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
39774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
39874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3992adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::attachToContext(GLuint tex) {
40074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
40174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
40274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
40374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
4052adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: abandoned GLConsumer");
40674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
40774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
40874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
4102adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: GLConsumer is already attached to a "
41174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
41274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
41374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
41474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
41674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
41774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
41974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
42074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
42174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
42274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
42474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
42574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
42674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
42774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
42974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
43074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    glBindTexture(mTexTarget, tex);
43174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
43274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
4335c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // The EGLImageKHR that was associated with the slot was destroyed when
4342adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        // the GLConsumer was detached from the old context, so we need to
4355c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // recreate it here.
436bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t err = bindUnslottedBufferLocked(dpy);
437bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err != NO_ERROR) {
43874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
43974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
44074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
44174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
44374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
44474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
44574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
44674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
44874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
44974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4502adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) {
451bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
452bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture, mCurrentTextureBuf.get());
453bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
454bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Create a temporary EGLImageKHR.
455bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
456bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (image == EGL_NO_IMAGE_KHR) {
457bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return UNKNOWN_ERROR;
458bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
459bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
460bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Attach the current buffer to the GL texture.
461bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
462bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
463bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
464bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = OK;
465bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
466bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
467bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                "(slot %d): %#04x", image, mCurrentTexture, error);
468bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        err = UNKNOWN_ERROR;
469bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
470bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
471bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We destroy the EGLImageKHR here because the current buffer may no
472bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // longer be associated with one of the buffer slots, so we have
473bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // nowhere to to store it.  If the buffer is still associated with a
474bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // slot then another EGLImageKHR will be created next time that buffer
475bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // gets acquired in updateTexImage.
476bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    eglDestroyImageKHR(dpy, image);
477bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
478bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
479bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
480bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
481bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
4822adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
48374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
48474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
48501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
486ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useNativeFenceSync()) {
48701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
48801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
48901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
49001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
49101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
49274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
49374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
49401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
49501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
49698ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
49701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
49801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
49901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
50001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
50101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
50201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
5039504eb915c9628e130f45019bdefda0168089886Jesse Hall            status_t err = addReleaseFenceLocked(mCurrentTexture, fence);
50401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
50501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error adding release fence: "
50601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
50701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
50801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
509ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
51001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
51101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
51201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
51301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
51401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
51501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
51601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
51701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
51801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: error waiting for previous "
51901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
52001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
52101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
52201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
52301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
52401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
52501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
52601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
52701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
52874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
52901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
53001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
53101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
53201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
53301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
53401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
53501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
53601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
53701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
53801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
53974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
54074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
54174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
54274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
54374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
54474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5452adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenbool GLConsumer::isExternalFormat(uint32_t format)
5467a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
5477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
5487a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
5497a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
5507a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
5517a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
5527a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
5537a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
5547a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5557a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
5567a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5577a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
5587a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
5597a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
5627a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5637a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5642adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenGLenum GLConsumer::getCurrentTextureTarget() const {
565fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
5667a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5677a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5682adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::getTransformMatrix(float mtx[16]) {
569f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
570736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
571736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
572736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
5732adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setFilteringEnabled(bool enabled) {
5745c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
575e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
5762adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
577e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
578e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
5795c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
5805c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
581e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
582e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf==NULL) {
583e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
584e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
585e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
586e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf != NULL) {
587e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
5885c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
5895c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
5905c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
5912adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::computeCurrentTransformMatrixLocked() {
592e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    ST_LOGV("computeCurrentTransformMatrixLocked");
593f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
594a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
595a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
596a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
597a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
598a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
599a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
600a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
601a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
602a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
603a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
604a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
605a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
606a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
607a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
608a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
609a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
610a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
611a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
612a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
613a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
614a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
615a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
616a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
617a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
618f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
619f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
620eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
621e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
622e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (buf == NULL) {
623e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
624e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
625e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
626d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    Rect cropRect = mCurrentCrop;
6275c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
6285c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferWidth = buf->getWidth();
6295c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferHeight = buf->getHeight();
630d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    if (!cropRect.isEmpty()) {
6315c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        float shrinkAmount = 0.0f;
6325c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (mFilteringEnabled) {
6335c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // In order to prevent bilinear sampling beyond the edge of the
6345c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // crop rectangle we may need to shrink it by 2 texels in each
6355c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // dimension.  Normally this would just need to take 1/2 a texel
6365c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // off each end, but because the chroma channels of YUV420 images
6375c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // are subsampled we may need to shrink the crop region by a whole
6385c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // texel on each side.
6395c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            switch (buf->getPixelFormat()) {
6405c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_8888:
6415c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBX_8888:
6425c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_888:
6435c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_565:
6445c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_BGRA_8888:
6455c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_5551:
6465c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_4444:
6475c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // We know there's no subsampling of any channels, so we
6485c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // only need to shrink by a half a pixel.
6495c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 0.5;
6504f9c284de4b9159126f69eb1219c410f66cc872cRomain Guy                    break;
6519fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
6525c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                default:
6535c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // If we don't recognize the format, we must assume the
6545c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // worst case (that we care about), which is YUV420.
6555c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 1.0;
6569fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    break;
6575c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
6585c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
6595c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
6605c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        // Only shrink the dimensions that are not the size of the buffer.
6615c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.width() < bufferWidth) {
6625c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
6635c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
6645c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferWidth;
6655c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
6665c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.height() < bufferHeight) {
6675c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
6685c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
6695c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
6705c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
6715c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
672a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
673f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
674a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
675a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
676f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
677d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
678f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
679f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
680a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
681a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
682a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
683a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
6842adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // coordinate of 0, so GLConsumer must behave the same way.  We don't
685a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
686a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
687736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
688f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
689f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
6902adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddennsecs_t GLConsumer::getTimestamp() {
6916ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
6921d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
6931d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
6941d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
6951d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
6962adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenEGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
6978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
6988ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
6998ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
7008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
7018ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
7028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
7038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
7048ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
7053cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
7063cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
707fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
7088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
7098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
7108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
7118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
7122adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
7137a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
7147a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
7157a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7167a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7172adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenRect GLConsumer::getCurrentCrop() const {
7187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
719016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
720016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
721016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
722016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newWidth = mCurrentCrop.width();
723016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newHeight = mCurrentCrop.height();
724016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
725016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
726016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
727016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too wide: newWidth = %d", newWidth);
728016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
729016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
730016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too tall: newHeight = %d", newHeight);
731016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
732016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
733016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
734016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth < mCurrentCrop.width()) {
735016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dw = (newWidth - mCurrentCrop.width())/2;
736016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
737016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
738016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
739016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newHeight < mCurrentCrop.height()) {
740016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dh = (newHeight - mCurrentCrop.height())/2;
741016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
742016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
743016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
744016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
745016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
746016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
747016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
748016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
749016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
750016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
7517a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7527a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7532adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentTransform() const {
7547a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
7557a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
7567a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7577a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7582adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentScalingMode() const {
7597734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
7607734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
7617734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
7627734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
7632adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<Fence> GLConsumer::getCurrentFence() const {
764dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
765dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
766dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
767dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
7682adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWait() const {
76961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
7703941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
7713941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
7723941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
7732adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWaitLocked() const {
77461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
77561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
77661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
77761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
77861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
77961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
78061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
78161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
78261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
78361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
78461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLContext");
78561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
78661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
78761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
7881df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (mCurrentFence->isValid()) {
789ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useWaitSync()) {
79061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
79161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
79261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
79361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
79461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
79561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
79661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
79761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
79861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
79961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
80061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
80161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
80261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
80361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
80461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
80561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
80661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
80761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
80861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
80961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
81061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
81161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
8122bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            eglWaitSyncKHR(dpy, sync, 0);
81361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
81461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
81561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
81661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
81761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
81861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
81961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
82061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
821ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall            status_t err = mCurrentFence->waitForever(1000,
8222adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    "GLConsumer::doGLFenceWaitLocked");
82361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
82461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
82561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
82661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
82761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
82861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
82961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
83061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
83161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
83261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
8332adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenbool GLConsumer::isSynchronousMode() const {
83459769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis    Mutex::Autolock lock(mMutex);
835b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->isSynchronousMode();
83659769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis}
83759769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis
8382adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::freeBufferLocked(int slotIndex) {
839fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
8409abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
8419abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
8429abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
8439fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
8449aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    if (img != EGL_NO_IMAGE_KHR) {
8459aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
8469aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        eglDestroyImageKHR(mEglDisplay, img);
847fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
8489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
8499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
850fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
851fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
8522adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::abandonLocked() {
8539fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ST_LOGV("abandonLocked");
8549fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mCurrentTextureBuf.clear();
8559fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
8567b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
8577b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
8582adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setName(const String8& name) {
859eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
860fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
861b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(name);
862b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
863b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8642adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
865b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
866b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
867b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
868b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8692adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
870b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
87185b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
872b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setConsumerUsageBits(usage);
873b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
874b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8752adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setTransformHint(uint32_t hint) {
876b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
877b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setTransformHint(hint);
878b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
879b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8802adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden// Used for refactoring BufferQueue from GLConsumer
8812adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden// Should not be in final interface once users of GLConsumer are clean up.
8822adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setSynchronousMode(bool enabled) {
883b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
884b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setSynchronousMode(enabled);
885b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
886b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
88774d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid GLConsumer::dumpLocked(String8& result, const char* prefix) const
88868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
88974d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
8909fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
8919fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
8929fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
8939fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
8949fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
89568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
89674d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    ConsumerBase::dumpLocked(result, prefix);
89768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
89868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
899f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
900f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
901f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
902f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
903f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
904f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
905f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
906f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
907f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
908f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
909f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
910f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
911f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
912f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
913f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
914f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
915f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
916f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
917f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
918f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
919f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
920f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
9218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
922