GLConsumer.cpp revision 45263e2475ac6a885dbd78eff7d4e44f374e5237
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>
28ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian#include <cutils/compiler.h>
298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
309fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis#include <hardware/hardware.h>
319fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
32ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian#include <gui/GLConsumer.h>
3390ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/IGraphicBufferAlloc.h>
3490ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/ISurfaceComposer.h>
3590ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <gui/SurfaceComposerClient.h>
3641f673c9b3aac0d96e41c928845c39186d565212Mathias Agopian
3790ac799241f077a7b7e6c1875fd933864c8dd2a7Mathias Agopian#include <private/gui/ComposerService.h>
38ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian#include <private/gui/SyncFeatures.h>
398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <utils/Log.h>
4168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian#include <utils/String8.h>
421c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#include <utils/Trace.h>
438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4497eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddennamespace android {
4597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
462adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden// Macros for including the GLConsumer name in log messages
476807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
489d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
49a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
5032397c1cd3327905173b36baa6fd1c579bc328ffSteve Block#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
51e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5229b5762efc359022168e5099c1d17925444d3147Mathias Agopian
53ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatic const struct {
54ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    size_t width, height;
55ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    char const* bits;
5645263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian} kDebugData = { 15, 12,
5745263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian    "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__"
5845263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian    "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________"
5945263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian};
60ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
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 Gennis
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
89fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
90db89edc94bd2a78226b407f9f7261e202e7fa325Mathias AgopianGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, GLuint tex,
91595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian        GLenum texTarget, bool useFenceSync, bool isControlledByApp) :
92595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian    ConsumerBase(bq, isControlledByApp),
931d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
94e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
951df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    mCurrentFence(Fence::NO_FENCE),
961d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
97e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultWidth(1),
98e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultHeight(1),
995c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
100b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
10186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
102eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
103ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
104ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
10574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
10674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1076b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
1082adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    ST_LOGV("GLConsumer");
109b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
110fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
111fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
112fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
113db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1162adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
1178072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
118db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultMaxBufferCount(bufferCount);
1198072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1208072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1222adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
123a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
124b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
125016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
126016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
127db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferSize(w, h);
128a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
129a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1302adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::updateTexImage() {
131bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
132bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("updateTexImage");
133bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
134bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
135bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
1362adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("updateTexImage: GLConsumer is abandoned!");
137bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
138bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
139bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
140bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
141bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
142bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
143bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
144bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
145bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
146bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    BufferQueue::BufferItem item;
147bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
148bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
149bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
150bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
1511585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    err = acquireBufferLocked(&item, 0);
152bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
153bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
154bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
155bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGV("updateTexImage: no buffers were available");
156bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
157bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
158bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
159bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("updateTexImage: acquire failed: %s (%d)",
160bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
161bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
162bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
163bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
164bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
165bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
166ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    err = updateAndReleaseLocked(item);
167bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
168bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
169bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
170bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
171bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
172bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
17397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
17497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
1752c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
1762c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
177ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
178ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::releaseTexImage() {
179ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ATRACE_CALL();
180ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ST_LOGV("releaseTexImage");
181ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    Mutex::Autolock lock(mMutex);
182ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
183ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (mAbandoned) {
184ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        ST_LOGE("releaseTexImage: GLConsumer is abandoned!");
185ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        return NO_INIT;
186ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
187ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
188ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Make sure the EGL state is the same as in previous calls.
189ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    status_t err = checkAndUpdateEglStateLocked();
190ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (err != NO_ERROR) {
191ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        return err;
192ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
193ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
194ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Update the GLConsumer state.
195ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    int buf = mCurrentTexture;
196ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
197ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
198ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        ST_LOGV("releaseTexImage:(slot=%d", buf);
199ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
200ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        // Do whatever sync ops we need to do before releasing the slot.
201ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        err = syncForReleaseLocked(mEglDisplay);
202ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (err != NO_ERROR) {
203ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
204ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            return err;
205ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
206ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
207ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
208ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                mEglDisplay, EGL_NO_SYNC_KHR);
209ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (err < NO_ERROR) {
210ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
211ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                    strerror(-err), err);
212ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            return err;
213ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
214ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
215ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (CC_UNLIKELY(mReleasedTexImageBuffer == NULL)) {
216ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            // The first time, create the debug texture in case the application
217ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            // continues to use it.
21845263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian            sp<GraphicBuffer> buffer = new GraphicBuffer(
21945263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian                    kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
220ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                    GraphicBuffer::USAGE_SW_WRITE_RARELY);
221ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            uint32_t* bits;
222ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
223ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            size_t w = buffer->getStride();
224ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            size_t h = buffer->getHeight();
225ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            memset(bits, 0, w*h*4);
226ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            for (size_t y=0 ; y<kDebugData.height ; y++) {
227ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                for (size_t x=0 ; x<kDebugData.width ; x++) {
22845263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian                    bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF;
229ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                }
230ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                bits += w;
231ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            }
232ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            buffer->unlock();
233ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            mReleasedTexImageBuffer = buffer;
234ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
235ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
236ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
237ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTextureBuf = mReleasedTexImageBuffer;
238ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentCrop.makeInvalid();
239ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTransform = 0;
240ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
241ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTimestamp = 0;
242ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentFence = Fence::NO_FENCE;
243ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
244ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        // bind a dummy texture
245ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        glBindTexture(mTexTarget, mTexName);
246ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        bindUnslottedBufferLocked(mEglDisplay);
247ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
248ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
249ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    return NO_ERROR;
250ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian}
251ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
2521585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFaddenstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
2531585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden        nsecs_t presentWhen) {
2541585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
2559fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
2569fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
2579fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
2589fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2599fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    int slot = item->mBuf;
2609fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (item->mGraphicBuffer != NULL) {
261bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // This buffer has not been acquired before, so we must assume
262bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // that any EGLImage in mEglSlots is stale.
2639fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
264bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
265bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
266bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                      slot);
267bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                // keep going
268bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            }
2699fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
2709fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
2719fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
2729fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2739fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
2749fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
2759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
276c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnarstatus_t GLConsumer::releaseBufferLocked(int buf,
277c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        sp<GraphicBuffer> graphicBuffer,
278c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        EGLDisplay display, EGLSyncKHR eglFence) {
279c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // release the buffer if it hasn't already been discarded by the
280c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // BufferQueue. This can happen, for example, when the producer of this
281c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // buffer has reallocated the original buffer slot after this buffer
282c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // was acquired.
283c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    status_t err = ConsumerBase::releaseBufferLocked(
284c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            buf, graphicBuffer, display, eglFence);
285d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
2869fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
2879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
2889fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
289ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
290bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
2919abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
2929abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
29374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
294ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
29574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
29674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
29774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
29874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
299bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
300bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
301bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
302bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
303ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
304ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
305bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    int buf = item.mBuf;
306bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
307bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // If the mEglSlot entry is empty, create an EGLImage for the gralloc
308bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // buffer currently in the slot in ConsumerBase.
309bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    //
310bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
311bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // means the buffer was previously acquired), if we destroyed the
312bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // EGLImage when detaching from a context but the buffer has not been
313bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // re-allocated.
314bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
315bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer);
316bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (image == EGL_NO_IMAGE_KHR) {
317ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
318bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                  mEglDisplay, buf);
319bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
320bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
321bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        mEglSlots[buf].mEglImage = image;
322ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
323ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
324bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
325bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = syncForReleaseLocked(mEglDisplay);
326bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
327bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // Release the buffer we just acquired.  It's not safe to
328bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // release the old buffer, so instead we just drop the new frame.
329c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // As we are still under lock since acquireBuffer, it is safe to
330c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // release by slot.
331c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
332c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mEglDisplay, EGL_NO_SYNC_KHR);
333bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
334bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
335ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
336ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
337bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture,
338bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
339bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            buf, mSlots[buf].mGraphicBuffer->handle);
340eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
341bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
342bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
343c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t status = releaseBufferLocked(
344c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mCurrentTexture, mCurrentTextureBuf, mEglDisplay,
345bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                mEglSlots[mCurrentTexture].mEglFence);
346ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (status < NO_ERROR) {
347ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
348bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                   strerror(-status), status);
349bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = status;
350bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // keep going, with error raised [?]
3512c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
352bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
3532c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
3542adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // Update the GLConsumer state.
355bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTexture = buf;
356bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
357bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
358bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
359bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
360bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
361bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
362bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
363bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
364bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
365bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
366bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
367bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
3682adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindTextureImageLocked() {
369bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
370bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
371bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
372bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
373bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
374bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
375bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
376bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
377bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
378bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
379bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
380bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
381bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (mCurrentTextureBuf == NULL) {
382bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: no currently-bound texture");
383bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return NO_INIT;
3848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
38597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        status_t err = bindUnslottedBufferLocked(mEglDisplay);
38697eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        if (err != NO_ERROR) {
38797eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden            return err;
38897eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        }
389bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    } else {
390bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
3910eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
3929fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
39374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3949fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
395bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: error binding external texture image %p"
396bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                    ": %#04x", image, error);
397bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
3988ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
399bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
40097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
40197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
40297eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
40397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
404bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
4059a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
4062adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::checkAndUpdateEglStateLocked() {
407bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
408bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
40986edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
410bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
411bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            dpy == EGL_NO_DISPLAY) {
412bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
413bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
414bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
415b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
416bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
417bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ctx == EGL_NO_CONTEXT) {
418bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
419bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
4208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
42150c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
422bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
423bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
424bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
4258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
4268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
42713f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hallvoid GLConsumer::setReleaseFence(const sp<Fence>& fence) {
42813f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall    if (fence->isValid() &&
42913f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
430c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t err = addReleaseFence(mCurrentTexture,
431c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mCurrentTextureBuf, fence);
43213f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        if (err != OK) {
43313f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
43413f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall                    strerror(-err), err);
43513f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        }
436ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
437ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
438ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
4392adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::detachFromContext() {
44074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
44174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
44274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
44374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
4452adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: abandoned GLConsumer");
44674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
44774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
44874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
4502adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: GLConsumer is not attached to a "
45174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
45274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
45374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
45474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
45674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
45774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
45974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
46074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
46174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
46274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
46374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
46474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
46574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
46674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
46774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
46874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
46974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
47074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
47174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
47274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
47374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
47474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
47574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
47674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4779aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // Because we're giving up the EGLDisplay we need to free all the EGLImages
4789aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // that are associated with it.  They'll be recreated when the
4792adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // GLConsumer gets attached to a new OpenGL ES context (and thus gets a
4809aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // new EGLDisplay).
4819aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
4829fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR img = mEglSlots[i].mEglImage;
4835c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
4849aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
4859fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
4869aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        }
4879aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    }
4889aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis
48974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
49074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
49174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
49274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
49374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
49474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
49574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4962adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::attachToContext(GLuint tex) {
49774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
49874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
49974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
50074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
50174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
5022adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: abandoned GLConsumer");
50374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
50474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
50574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
50674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
5072adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: GLConsumer is already attached to a "
50874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
50974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
51074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
51174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
51274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
51374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
51474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
51574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
51674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
51774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
51874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
51974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
52074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
52174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
52274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
52374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
52474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
52574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
52674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
52774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    glBindTexture(mTexTarget, tex);
52874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
52974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
5305c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // The EGLImageKHR that was associated with the slot was destroyed when
5312adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        // the GLConsumer was detached from the old context, so we need to
5325c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // recreate it here.
533bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t err = bindUnslottedBufferLocked(dpy);
534bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err != NO_ERROR) {
53574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
53674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
53774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
53874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
53974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
54074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
54174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
54274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
54374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
54474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
54574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
54674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) {
548bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
549bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture, mCurrentTextureBuf.get());
550bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
551bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Create a temporary EGLImageKHR.
552bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
553bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (image == EGL_NO_IMAGE_KHR) {
554bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return UNKNOWN_ERROR;
555bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
556bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
557bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Attach the current buffer to the GL texture.
558bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
559bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
560bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
561bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = OK;
562bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
563bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
564bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                "(slot %d): %#04x", image, mCurrentTexture, error);
565bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        err = UNKNOWN_ERROR;
566bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
567bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
568bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We destroy the EGLImageKHR here because the current buffer may no
569bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // longer be associated with one of the buffer slots, so we have
570bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // nowhere to to store it.  If the buffer is still associated with a
571bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // slot then another EGLImageKHR will be created next time that buffer
572bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // gets acquired in updateTexImage.
573bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    eglDestroyImageKHR(dpy, image);
574bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
575bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
576bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
577bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
578bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
5792adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
58074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
58174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
583ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useNativeFenceSync()) {
58401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
58501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
58601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
58701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
58801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
58974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
59074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
59101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
59201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
59398ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
59401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
59501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
59601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
59701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
59801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
59901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
600c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            status_t err = addReleaseFenceLocked(mCurrentTexture,
601c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                    mCurrentTextureBuf, fence);
60201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
60301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error adding release fence: "
60401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
60501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
60601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
607ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
60801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
60901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
61001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
61101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
61201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
61301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
61401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
61501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
61601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: error waiting for previous "
61701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
61801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
61901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
62001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
62101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
62201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
62301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
62401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
62501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
62674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
62801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
62901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
63001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
63101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
63201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
63301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
63401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
63501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
63601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
63774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
63874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
63974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
64074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
64174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
64274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
6432adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenbool GLConsumer::isExternalFormat(uint32_t format)
6447a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
6457a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
6467a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
6477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
6487a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
6497a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
6507a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
6517a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
6527a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
6537a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
6547a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6557a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
6567a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
6577a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
6587a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6597a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
6607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6622adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenGLenum GLConsumer::getCurrentTextureTarget() const {
663fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
6647a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
6657a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
6662adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::getTransformMatrix(float mtx[16]) {
667f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
668736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
669736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
670736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
6712adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setFilteringEnabled(bool enabled) {
6725c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
673e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
6742adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
675e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
676e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
6775c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
6785c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
679e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
680e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf==NULL) {
681e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
682e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
683e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
684e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf != NULL) {
685e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
6865c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
6875c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
6885c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
6892adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::computeCurrentTransformMatrixLocked() {
690e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    ST_LOGV("computeCurrentTransformMatrixLocked");
691f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
692a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
693a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
694a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
695a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
696a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
697a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
698a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
699a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
700a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
701a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
702a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
703a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
704a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
705a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
706a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
707a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
708a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
709a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
710a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
711a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
712a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
713a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
714a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
715a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
716f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
717f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
718eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
719e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
720e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (buf == NULL) {
721e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
722e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
723e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
724d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    Rect cropRect = mCurrentCrop;
7255c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
7265c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferWidth = buf->getWidth();
7275c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferHeight = buf->getHeight();
728d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    if (!cropRect.isEmpty()) {
7295c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        float shrinkAmount = 0.0f;
7305c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (mFilteringEnabled) {
7315c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // In order to prevent bilinear sampling beyond the edge of the
7325c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // crop rectangle we may need to shrink it by 2 texels in each
7335c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // dimension.  Normally this would just need to take 1/2 a texel
7345c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // off each end, but because the chroma channels of YUV420 images
7355c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // are subsampled we may need to shrink the crop region by a whole
7365c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // texel on each side.
7375c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            switch (buf->getPixelFormat()) {
7385c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_8888:
7395c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBX_8888:
7405c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_888:
7415c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_565:
7425c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_BGRA_8888:
7435c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // We know there's no subsampling of any channels, so we
7445c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // only need to shrink by a half a pixel.
7455c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 0.5;
7464f9c284de4b9159126f69eb1219c410f66cc872cRomain Guy                    break;
7479fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
7485c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                default:
7495c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // If we don't recognize the format, we must assume the
7505c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // worst case (that we care about), which is YUV420.
7515c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 1.0;
7529fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    break;
7535c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
7545c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
7555c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
7565c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        // Only shrink the dimensions that are not the size of the buffer.
7575c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.width() < bufferWidth) {
7585c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
7595c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
7605c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferWidth;
7615c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
7625c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.height() < bufferHeight) {
7635c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
7645c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
7655c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
7665c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
7675c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
768a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
769f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
770a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
771a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
772f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
773d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
774f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
775f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
776a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
777a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
778a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
779a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
7802adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // coordinate of 0, so GLConsumer must behave the same way.  We don't
781a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
782a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
783736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
784f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
785f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
7862adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddennsecs_t GLConsumer::getTimestamp() {
7876ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
7881d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
7891d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
7901d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
7911d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
7922adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenEGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
7938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
7948ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
7958ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
7968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
7978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
7988ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
7998ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
8008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
8013cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
8023cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
803fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
8048ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
8058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
8068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
8078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
8082adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
8097a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
8107a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
8117a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
8127a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
8132adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenRect GLConsumer::getCurrentCrop() const {
8147a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
815016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
816016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
817016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
818016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newWidth = mCurrentCrop.width();
819016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newHeight = mCurrentCrop.height();
820016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
821016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
822016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
823016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too wide: newWidth = %d", newWidth);
824016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
825016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
826016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too tall: newHeight = %d", newHeight);
827016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
828016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
829016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
830016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth < mCurrentCrop.width()) {
831016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dw = (newWidth - mCurrentCrop.width())/2;
832016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
833016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
834016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
835016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newHeight < mCurrentCrop.height()) {
836016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dh = (newHeight - mCurrentCrop.height())/2;
837016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
838016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
839016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
840016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
841016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
842016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
843016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
844016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
845016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
846016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
8477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
8487a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
8492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentTransform() const {
8507a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
8517a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
8527a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
8537a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
8542adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentScalingMode() const {
8557734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
8567734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
8577734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
8587734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
8592adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<Fence> GLConsumer::getCurrentFence() const {
860dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
861dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
862dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
863dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
8642adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWait() const {
86561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
8663941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
8673941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
8683941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
8692adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWaitLocked() const {
87061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
87161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
87261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
87361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
87461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
87561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
87661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
87761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
87861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
87961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
88061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLContext");
88161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
88261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
88361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
8841df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (mCurrentFence->isValid()) {
885ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useWaitSync()) {
88661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
88761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
88861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
88961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
89061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
89161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
89261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
89361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
89461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
89561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
89661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
89761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
89861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
89961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
90061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
90161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
90261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
90361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
90461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
90561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
90661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
90761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
9082bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            eglWaitSyncKHR(dpy, sync, 0);
90961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
91061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
91161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
91261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
91361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
91461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
91561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
91661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
917ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopian            status_t err = mCurrentFence->waitForever(
9182adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    "GLConsumer::doGLFenceWaitLocked");
91961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
92061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
92161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
92261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
92361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
92461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
92561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
92661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
92761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
92861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
9292adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::freeBufferLocked(int slotIndex) {
930fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
9319abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
9329abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
9339abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
9349fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
9359aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    if (img != EGL_NO_IMAGE_KHR) {
9369aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
9379aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        eglDestroyImageKHR(mEglDisplay, img);
938fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
9399fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
9409fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
941fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
942fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
9432adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::abandonLocked() {
9449fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ST_LOGV("abandonLocked");
9459fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mCurrentTextureBuf.clear();
9469fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
9477b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
9487b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
9492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setName(const String8& name) {
950eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
951fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
952db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerName(name);
953b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
954b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
9552adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
956b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
957db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferFormat(defaultFormat);
958b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
959b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
9602adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
961b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
96285b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
963db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setConsumerUsageBits(usage);
964b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
965b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
9662adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setTransformHint(uint32_t hint) {
967b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
968db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setTransformHint(hint);
969b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
970b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
97174d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid GLConsumer::dumpLocked(String8& result, const char* prefix) const
97268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
97374d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
9749fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
9759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
9769fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
9779fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
9789fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
97968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
98074d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    ConsumerBase::dumpLocked(result, prefix);
98168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
98268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
983f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
984f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
985f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
986f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
987f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
988f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
989f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
990f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
991f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
992f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
993f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
994f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
995f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
996f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
997f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
998f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
999f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1000f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1001f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1002f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1003f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
1004f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
10058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
1006