GLConsumer.cpp revision 595264f1af12e25dce57d7c5b1d52ed86ac0d0c9
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
818f938a53385a3c6d1c6aa24b3f38437bb2cc47aeMathias AgopianGLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex,
82595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian        GLenum texTarget, bool useFenceSync, bool isControlledByApp) :
83595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian    ConsumerBase(bq, isControlledByApp),
841d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
85e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
861df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    mCurrentFence(Fence::NO_FENCE),
871d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
88e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultWidth(1),
89e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultHeight(1),
905c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
91b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
9286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
93eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
94ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
95ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
9674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
9774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
986b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
992adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    ST_LOGV("GLConsumer");
100b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
101fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
102fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
103fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
1049fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1072adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
1088072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
10931a353da225af5329735451c761b430d82dfda1bJamie Gennis    return mBufferQueue->setDefaultMaxBufferCount(bufferCount);
1108072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1118072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1132adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
114a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
115b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
116016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
117016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
118b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferSize(w, h);
119a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
120a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1212adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::updateTexImage() {
122bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
123bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("updateTexImage");
124bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
125bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
126bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
1272adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("updateTexImage: GLConsumer is abandoned!");
128bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
129bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
130bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
131bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
132bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
133bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
134bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
135bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
136bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
137bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    BufferQueue::BufferItem item;
138bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
139bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
140bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
141bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
1421585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    err = acquireBufferLocked(&item, 0);
143bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
144bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
145bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
146bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGV("updateTexImage: no buffers were available");
147bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
148bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
149bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
150bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("updateTexImage: acquire failed: %s (%d)",
151bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
152bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
153bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
154bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
155bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
156bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
157bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = releaseAndUpdateLocked(item);
158bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
159bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
160bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
161bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
162bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
163bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
16497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
16597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
1662c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
1672c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
1681585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFaddenstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
1691585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden        nsecs_t presentWhen) {
1701585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
1719fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
1729fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
1739fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1749fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    int slot = item->mBuf;
1769fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (item->mGraphicBuffer != NULL) {
177bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // This buffer has not been acquired before, so we must assume
178bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // that any EGLImage in mEglSlots is stale.
1799fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
180bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
181bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
182bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                      slot);
183bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                // keep going
184bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            }
1859fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
1869fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
1879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
1889fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
1899fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
1909fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
1919fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
192c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnarstatus_t GLConsumer::releaseBufferLocked(int buf,
193c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        sp<GraphicBuffer> graphicBuffer,
194c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        EGLDisplay display, EGLSyncKHR eglFence) {
195c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // release the buffer if it hasn't already been discarded by the
196c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // BufferQueue. This can happen, for example, when the producer of this
197c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // buffer has reallocated the original buffer slot after this buffer
198c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // was acquired.
199c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    status_t err = ConsumerBase::releaseBufferLocked(
200c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            buf, graphicBuffer, display, eglFence);
201d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
2029fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
2039fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
2049fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
2052adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item)
206bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
2079abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
2089abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
20974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
2102adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("releaseAndUpdate: GLConsumer is not attached to an OpenGL "
21174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
21274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
21374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
21474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
215bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
216bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
217bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
218bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
219ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
220ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
221bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    int buf = item.mBuf;
222bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
223bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // If the mEglSlot entry is empty, create an EGLImage for the gralloc
224bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // buffer currently in the slot in ConsumerBase.
225bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    //
226bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
227bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // means the buffer was previously acquired), if we destroyed the
228bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // EGLImage when detaching from a context but the buffer has not been
229bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // re-allocated.
230bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
231bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer);
232bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (image == EGL_NO_IMAGE_KHR) {
233bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGW("releaseAndUpdate: unable to createImage on display=%p slot=%d",
234bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                  mEglDisplay, buf);
235bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
236bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
237bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        mEglSlots[buf].mEglImage = image;
238ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
239ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
240bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
241bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = syncForReleaseLocked(mEglDisplay);
242bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
243bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // Release the buffer we just acquired.  It's not safe to
244bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // release the old buffer, so instead we just drop the new frame.
245c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // As we are still under lock since acquireBuffer, it is safe to
246c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // release by slot.
247c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
248c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mEglDisplay, EGL_NO_SYNC_KHR);
249bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
250bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
251ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
252bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("releaseAndUpdate: (slot=%d buf=%p) -> (slot=%d buf=%p)",
253bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture,
254bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
255bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            buf, mSlots[buf].mGraphicBuffer->handle);
256eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
257bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
258bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
259c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t status = releaseBufferLocked(
260c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mCurrentTexture, mCurrentTextureBuf, mEglDisplay,
261bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                mEglSlots[mCurrentTexture].mEglFence);
262bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
263bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)",
264bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                   strerror(-status), status);
265bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = status;
266bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // keep going, with error raised [?]
2672c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
268bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
2692c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
2702adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // Update the GLConsumer state.
271bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTexture = buf;
272bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
273bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
274bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
275bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
276bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
277bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
278bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
279bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
280bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
281bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
282bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
283bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
2842adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindTextureImageLocked() {
285bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
286bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
287bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
288bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
289bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
290bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
291bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
292bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
293bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
294bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
295bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
296bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
297bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (mCurrentTextureBuf == NULL) {
298bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: no currently-bound texture");
299bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return NO_INIT;
3008ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
30197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        status_t err = bindUnslottedBufferLocked(mEglDisplay);
30297eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        if (err != NO_ERROR) {
30397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden            return err;
30497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        }
305bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    } else {
306bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
3070eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
3089fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
30974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3109fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
311bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: error binding external texture image %p"
312bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                    ": %#04x", image, error);
313bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
3148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
315bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
31697eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
31797eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
31897eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
31997eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
320bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
3219a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
3222adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::checkAndUpdateEglStateLocked() {
323bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
324bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
32586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
326bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
327bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            dpy == EGL_NO_DISPLAY) {
328bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
329bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
330bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
331b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
332bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
333bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ctx == EGL_NO_CONTEXT) {
334bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
335bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
3368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
33750c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
338bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
339bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
340bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
3418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
3428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
34313f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hallvoid GLConsumer::setReleaseFence(const sp<Fence>& fence) {
34413f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall    if (fence->isValid() &&
34513f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
346c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t err = addReleaseFence(mCurrentTexture,
347c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mCurrentTextureBuf, fence);
34813f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        if (err != OK) {
34913f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
35013f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall                    strerror(-err), err);
35113f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        }
352ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
353ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
354ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
3552adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::detachFromContext() {
35674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
35774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
35874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
35974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
36074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
3612adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: abandoned GLConsumer");
36274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
36374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
36474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
36574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
3662adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: GLConsumer is not attached to a "
36774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
36874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
36974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
37074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
37274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
37374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
37574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
37674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
37774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
37874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
37974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
38074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
38174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
38274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
38374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
38474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
38574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
38674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
38774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
38874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
38974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
39074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
39174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
39274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
3939aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // Because we're giving up the EGLDisplay we need to free all the EGLImages
3949aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // that are associated with it.  They'll be recreated when the
3952adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // GLConsumer gets attached to a new OpenGL ES context (and thus gets a
3969aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // new EGLDisplay).
3979aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
3989fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR img = mEglSlots[i].mEglImage;
3995c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
4009aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
4019fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
4029aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        }
4039aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    }
4049aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis
40574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
40674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
40774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
40874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
40974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
41074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
41174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4122adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::attachToContext(GLuint tex) {
41374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
41474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
41574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
41674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
41774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
4182adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: abandoned GLConsumer");
41974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
42074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
42174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
4232adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: GLConsumer is already attached to a "
42474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
42574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
42674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
42774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
42874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
42974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
43074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
43174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
43274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
43374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
43474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
43574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
43674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
43774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
43874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
43974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
44074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
44274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
44374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    glBindTexture(mTexTarget, tex);
44474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
44574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
4465c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // The EGLImageKHR that was associated with the slot was destroyed when
4472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        // the GLConsumer was detached from the old context, so we need to
4485c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // recreate it here.
449bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t err = bindUnslottedBufferLocked(dpy);
450bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err != NO_ERROR) {
45174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
45274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
45374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
45474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
45574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
45674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
45774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
45874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
45974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
46074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
46174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
46274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4632adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) {
464bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
465bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture, mCurrentTextureBuf.get());
466bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
467bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Create a temporary EGLImageKHR.
468bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
469bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (image == EGL_NO_IMAGE_KHR) {
470bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return UNKNOWN_ERROR;
471bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
472bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
473bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Attach the current buffer to the GL texture.
474bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
475bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
476bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
477bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = OK;
478bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
479bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
480bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                "(slot %d): %#04x", image, mCurrentTexture, error);
481bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        err = UNKNOWN_ERROR;
482bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
483bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
484bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We destroy the EGLImageKHR here because the current buffer may no
485bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // longer be associated with one of the buffer slots, so we have
486bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // nowhere to to store it.  If the buffer is still associated with a
487bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // slot then another EGLImageKHR will be created next time that buffer
488bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // gets acquired in updateTexImage.
489bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    eglDestroyImageKHR(dpy, image);
490bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
491bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
492bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
493bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
494bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
4952adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
49674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
49774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
49801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
499ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useNativeFenceSync()) {
50001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
50101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
50201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
50301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
50401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
50574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
50674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
50701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
50801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
50998ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
51001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
51101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
51201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
51301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
51401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
51501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
516c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            status_t err = addReleaseFenceLocked(mCurrentTexture,
517c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                    mCurrentTextureBuf, fence);
51801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
51901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error adding release fence: "
52001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
52101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
52201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
523ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
52401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
52501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
52601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
52701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
52801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
52901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
53001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
53101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
53201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: error waiting for previous "
53301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
53401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
53501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
53601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
53701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
53801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
53901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
54001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
54101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
54274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
54301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
54401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
54501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
54601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
54701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
54801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
54901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
55001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
55101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
55201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
55374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
55474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
55574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
55674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
55774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
55874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5592adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenbool GLConsumer::isExternalFormat(uint32_t format)
5607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
5617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
5627a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
5637a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
5647a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
5657a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
5667a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
5677a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
5687a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5697a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
5707a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5717a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
5727a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
5737a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
5747a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5757a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
5767a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5777a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5782adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenGLenum GLConsumer::getCurrentTextureTarget() const {
579fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
5807a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5817a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5822adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::getTransformMatrix(float mtx[16]) {
583f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
584736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
585736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
586736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
5872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setFilteringEnabled(bool enabled) {
5885c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
589e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
5902adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
591e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
592e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
5935c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
5945c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
595e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
596e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf==NULL) {
597e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
598e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
599e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
600e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf != NULL) {
601e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
6025c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
6035c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
6045c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
6052adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::computeCurrentTransformMatrixLocked() {
606e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    ST_LOGV("computeCurrentTransformMatrixLocked");
607f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
608a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
609a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
610a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
611a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
612a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
613a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
614a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
615a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
616a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
617a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
618a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
619a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
620a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
621a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
622a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
623a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
624a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
625a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
626a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
627a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
628a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
629a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
630a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
631a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
632f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
633f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
634eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
635e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
636e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (buf == NULL) {
637e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
638e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
639e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
640d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    Rect cropRect = mCurrentCrop;
6415c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
6425c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferWidth = buf->getWidth();
6435c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    float bufferHeight = buf->getHeight();
644d72f233ffa125856a44976a50a66ceb669f49ab2Jamie Gennis    if (!cropRect.isEmpty()) {
6455c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        float shrinkAmount = 0.0f;
6465c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (mFilteringEnabled) {
6475c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // In order to prevent bilinear sampling beyond the edge of the
6485c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // crop rectangle we may need to shrink it by 2 texels in each
6495c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // dimension.  Normally this would just need to take 1/2 a texel
6505c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // off each end, but because the chroma channels of YUV420 images
6515c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // are subsampled we may need to shrink the crop region by a whole
6525c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            // texel on each side.
6535c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            switch (buf->getPixelFormat()) {
6545c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_8888:
6555c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBX_8888:
6565c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_888:
6575c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGB_565:
6585c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_BGRA_8888:
6595c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_5551:
6605c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                case PIXEL_FORMAT_RGBA_4444:
6615c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // We know there's no subsampling of any channels, so we
6625c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // only need to shrink by a half a pixel.
6635c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 0.5;
6644f9c284de4b9159126f69eb1219c410f66cc872cRomain Guy                    break;
6659fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
6665c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                default:
6675c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // If we don't recognize the format, we must assume the
6685c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    // worst case (that we care about), which is YUV420.
6695c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    shrinkAmount = 1.0;
6709fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis                    break;
6715c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
6725c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
6735c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
6745c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        // Only shrink the dimensions that are not the size of the buffer.
6755c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.width() < bufferWidth) {
6765c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
6775c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
6785c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferWidth;
6795c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
6805c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        if (cropRect.height() < bufferHeight) {
6815c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
6825c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
6835c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
6845c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis                    bufferHeight;
6855c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
686a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
687f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
688a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
689a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
690f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
691d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
692f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
693f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
694a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
695a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
696a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
697a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
6982adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // coordinate of 0, so GLConsumer must behave the same way.  We don't
699a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
700a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
701736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
702f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
703f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
7042adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddennsecs_t GLConsumer::getTimestamp() {
7056ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
7061d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
7071d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
7081d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
7091d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
7102adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenEGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
7118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
7128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
7138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
7148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
7158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
7168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
7178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
7188ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
7193cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
7203cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
721fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
7228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
7238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
7248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
7258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
7262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
7277a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
7287a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
7297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7312adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenRect GLConsumer::getCurrentCrop() const {
7327a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
733016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
734016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
735016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
736016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newWidth = mCurrentCrop.width();
737016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newHeight = mCurrentCrop.height();
738016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
739016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
740016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
741016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too wide: newWidth = %d", newWidth);
742016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
743016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
744016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too tall: newHeight = %d", newHeight);
745016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
746016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
747016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
748016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth < mCurrentCrop.width()) {
749016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dw = (newWidth - mCurrentCrop.width())/2;
750016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
751016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
752016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
753016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newHeight < mCurrentCrop.height()) {
754016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dh = (newHeight - mCurrentCrop.height())/2;
755016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
756016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
757016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
758016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
759016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
760016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
761016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
762016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
763016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
764016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
7657a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7667a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7672adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentTransform() const {
7687a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
7697a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
7707a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7717a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7722adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentScalingMode() const {
7737734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
7747734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
7757734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
7767734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
7772adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<Fence> GLConsumer::getCurrentFence() const {
778dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
779dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
780dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
781dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
7822adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWait() const {
78361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
7843941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
7853941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
7863941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
7872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWaitLocked() const {
78861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
78961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
79061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
79161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
79261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
79361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
79461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
79561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
79661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
79761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
79861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLContext");
79961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
80061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
80161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
8021df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (mCurrentFence->isValid()) {
803ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useWaitSync()) {
80461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
80561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
80661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
80761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
80861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
80961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
81061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
81161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
81261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
81361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
81461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
81561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
81661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
81761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
81861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
81961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
82061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
82161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
82261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
82361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
82461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
82561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
8262bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            eglWaitSyncKHR(dpy, sync, 0);
82761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
82861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
82961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
83061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
83161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
83261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
83361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
83461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
835ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopian            status_t err = mCurrentFence->waitForever(
8362adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    "GLConsumer::doGLFenceWaitLocked");
83761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
83861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
83961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
84061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
84161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
84261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
84361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
84461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
84561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
84661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
8472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::freeBufferLocked(int slotIndex) {
848fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
8499abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
8509abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
8519abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
8529fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
8539aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    if (img != EGL_NO_IMAGE_KHR) {
8549aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
8559aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        eglDestroyImageKHR(mEglDisplay, img);
856fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
8579fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
8589fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
859fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
860fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
8612adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::abandonLocked() {
8629fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ST_LOGV("abandonLocked");
8639fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mCurrentTextureBuf.clear();
8649fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
8657b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
8667b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
8672adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setName(const String8& name) {
868eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
869fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
870b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    mBufferQueue->setConsumerName(name);
871b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
872b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8732adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
874b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
875b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setDefaultBufferFormat(defaultFormat);
876b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
877b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8782adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
879b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
88085b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
881b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setConsumerUsageBits(usage);
882b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
883b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
8842adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setTransformHint(uint32_t hint) {
885b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
886b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    return mBufferQueue->setTransformHint(hint);
887b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
888b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
88974d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid GLConsumer::dumpLocked(String8& result, const char* prefix) const
89068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
89174d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
8929fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
8939fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
8949fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
8959fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
8969fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
89768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
89874d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    ConsumerBase::dumpLocked(result, prefix);
89968c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
90068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
901f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
902f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
903f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
904f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
905f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
906f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
907f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
908f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
909f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
910f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
911f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
912f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
913f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
914f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
915f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
916f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
917f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
918f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
919f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
920f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
921f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
922f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
9238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
924