GLConsumer.cpp revision 87a678478005026d950bedec49ee80b693777b95
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
44dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie GennisEGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
45dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis#define CROP_EXT_STR "EGL_ANDROID_image_crop"
46dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
4797eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddennamespace android {
4897eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden// Macros for including the GLConsumer name in log messages
506807e59e0ff943cc6225d46e3c33a8a7eae9b3d7Steve Block#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
519d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
52a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
5332397c1cd3327905173b36baa6fd1c579bc328ffSteve Block#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
54e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5529b5762efc359022168e5099c1d17925444d3147Mathias Agopian
56ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatic const struct {
57ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    size_t width, height;
58ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    char const* bits;
5945263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian} kDebugData = { 15, 12,
6045263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian    "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__"
6145263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian    "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________"
6245263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian};
63ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
64f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
65f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
66f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
67f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
68f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
69f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
70f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
71f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
72f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
73f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
929870c9b66cc73ee31aabba23aa06deaf673ee5efMathias AgopianMutex GLConsumer::sStaticInitLock;
939870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopiansp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
94fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
95dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool hasEglAndroidImageCropImpl() {
96dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
97dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
98dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    size_t cropExtLen = strlen(CROP_EXT_STR);
99dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    size_t extsLen = strlen(exts);
100dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool equal = !strcmp(CROP_EXT_STR, exts);
101dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
102dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool atEnd = (cropExtLen+1) < extsLen &&
103dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
104dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
105dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return equal || atStart || atEnd || inMiddle;
106dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
107dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
108dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool hasEglAndroidImageCrop() {
109dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    // Only compute whether the extension is present once the first time this
110dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    // function is called.
111dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    static bool hasIt = hasEglAndroidImageCropImpl();
112dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return hasIt;
113dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
114dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
115dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool isEglImageCroppable(const Rect& crop) {
116dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
117dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
118dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
1193f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
1203f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
121595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian    ConsumerBase(bq, isControlledByApp),
1221d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
123e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
1241df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    mCurrentFence(Fence::NO_FENCE),
1251d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
126d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    mCurrentFrameNumber(0),
127e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultWidth(1),
128e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultHeight(1),
1295c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
130b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
13186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
132eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
133ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
134ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
13574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
13674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1376b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
1382adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    ST_LOGV("GLConsumer");
139b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
140fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
141fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
142fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
143db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1462adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
1478072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
148db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultMaxBufferCount(bufferCount);
1498072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1508072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1518ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1522adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
153a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
154b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
155016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
156016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
157db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferSize(w, h);
158a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
159a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1602adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::updateTexImage() {
161bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
162bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("updateTexImage");
163bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
164bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
165bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
1662adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("updateTexImage: GLConsumer is abandoned!");
167bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
168bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
169bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
170bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
171bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
172bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
173bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
174bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
175bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
176bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    BufferQueue::BufferItem item;
177bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
178bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
179bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
180bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
1811585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    err = acquireBufferLocked(&item, 0);
182bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
183bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
184bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
185bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGV("updateTexImage: no buffers were available");
186bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
187bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
188bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
189bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("updateTexImage: acquire failed: %s (%d)",
190bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
191bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
192bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
193bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
194bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
195bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
196ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    err = updateAndReleaseLocked(item);
197bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
198bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
199bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
200bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
201bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
202bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
20397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
20497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
2052c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
2062c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
207ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
208ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::releaseTexImage() {
209ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ATRACE_CALL();
210ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ST_LOGV("releaseTexImage");
211ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    Mutex::Autolock lock(mMutex);
212ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
213ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (mAbandoned) {
214ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        ST_LOGE("releaseTexImage: GLConsumer is abandoned!");
215ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        return NO_INIT;
216ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
217ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
218ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Make sure the EGL state is the same as in previous calls.
21945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    status_t err = NO_ERROR;
22045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian
22145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mAttached) {
22245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        err = checkAndUpdateEglStateLocked(true);
22345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (err != NO_ERROR) {
22445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            return err;
22545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
22645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    } else {
22745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // if we're detached, no need to validate EGL's state -- we won't use it.
228ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
229ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
230ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Update the GLConsumer state.
231ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    int buf = mCurrentTexture;
232ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
233ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
23445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        ST_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
235ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
23645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mAttached) {
23745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // Do whatever sync ops we need to do before releasing the slot.
23845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            err = syncForReleaseLocked(mEglDisplay);
23945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            if (err != NO_ERROR) {
24045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian                ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
24145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian                return err;
24245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            }
24345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        } else {
24445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // if we're detached, we just use the fence that was created in detachFromContext()
24545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // so... basically, nothing more to do here.
246ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
247ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
24845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
249ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (err < NO_ERROR) {
250ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
251ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                    strerror(-err), err);
252ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            return err;
253ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
254ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
255ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
2569870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        mCurrentTextureBuf = getDebugTexImageBuffer();
257ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentCrop.makeInvalid();
258ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTransform = 0;
259ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
260ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTimestamp = 0;
261ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentFence = Fence::NO_FENCE;
262ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
26345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mAttached) {
26445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // bind a dummy texture
26545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            glBindTexture(mTexTarget, mTexName);
26645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            bindUnslottedBufferLocked(mEglDisplay);
26745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        } else {
26845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // detached, don't touch the texture (and we may not even have an
26945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // EGLDisplay here.
27045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
271ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
272ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
273ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    return NO_ERROR;
274ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian}
275ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
2769870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopiansp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
2779870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    Mutex::Autolock _l(sStaticInitLock);
2789870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
2799870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        // The first time, create the debug texture in case the application
2809870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        // continues to use it.
2819870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        sp<GraphicBuffer> buffer = new GraphicBuffer(
2829870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian                kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
2839870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian                GraphicBuffer::USAGE_SW_WRITE_RARELY);
2849870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        uint32_t* bits;
2859870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
2869870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        size_t w = buffer->getStride();
2879870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        size_t h = buffer->getHeight();
2889870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        memset(bits, 0, w*h*4);
2899870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        for (size_t y=0 ; y<kDebugData.height ; y++) {
2909870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian            for (size_t x=0 ; x<kDebugData.width ; x++) {
2919870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian                bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF;
2929870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian            }
2939870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian            bits += w;
2949870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        }
2959870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        buffer->unlock();
2969870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        sReleasedTexImageBuffer = buffer;
2979870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    }
2989870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    return sReleasedTexImageBuffer;
2999870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian}
3009870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian
3011585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFaddenstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
3021585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden        nsecs_t presentWhen) {
3031585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
3049fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
3059fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
3069fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
3079fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
3089fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    int slot = item->mBuf;
309dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool destroyEglImage = false;
310dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
311dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
312dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        if (item->mGraphicBuffer != NULL) {
313dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // This buffer has not been acquired before, so we must assume
314dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // that any EGLImage in mEglSlots is stale.
315dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            destroyEglImage = true;
316dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        } else if (mEglSlots[slot].mCropRect != item->mCrop) {
317dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // We've already seen this buffer before, but it now has a
318dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // different crop rect, so we'll need to recreate the EGLImage if
319dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // we're using the EGL_ANDROID_image_crop extension.
320dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            destroyEglImage = hasEglAndroidImageCrop();
321dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        }
322dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    }
323dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
324dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    if (destroyEglImage) {
325dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
326dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
327dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                  slot);
328dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // keep going
3299fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        }
330dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
3319fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
3329fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
3339fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
3349fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
3359fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
336c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnarstatus_t GLConsumer::releaseBufferLocked(int buf,
337c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        sp<GraphicBuffer> graphicBuffer,
338c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        EGLDisplay display, EGLSyncKHR eglFence) {
339c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // release the buffer if it hasn't already been discarded by the
340c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // BufferQueue. This can happen, for example, when the producer of this
341c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // buffer has reallocated the original buffer slot after this buffer
342c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // was acquired.
343c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    status_t err = ConsumerBase::releaseBufferLocked(
344c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            buf, graphicBuffer, display, eglFence);
345d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
3469fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
3479fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
3489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
349ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
350bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
3519abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
3529abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
35387a678478005026d950bedec49ee80b693777b95Andy McFadden    int buf = item.mBuf;
35487a678478005026d950bedec49ee80b693777b95Andy McFadden
35574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
356ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
35774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
35887a678478005026d950bedec49ee80b693777b95Andy McFadden        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
35987a678478005026d950bedec49ee80b693777b95Andy McFadden                mEglDisplay, EGL_NO_SYNC_KHR);
36074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
36174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
36274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
363bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
364bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
365bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
36687a678478005026d950bedec49ee80b693777b95Andy McFadden        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
36787a678478005026d950bedec49ee80b693777b95Andy McFadden                mEglDisplay, EGL_NO_SYNC_KHR);
368bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
369ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
370ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
371bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // If the mEglSlot entry is empty, create an EGLImage for the gralloc
372bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // buffer currently in the slot in ConsumerBase.
373bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    //
374bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
375bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // means the buffer was previously acquired), if we destroyed the
376bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // EGLImage when detaching from a context but the buffer has not been
377bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // re-allocated.
378bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
379dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        EGLImageKHR image = createImage(mEglDisplay,
380dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                mSlots[buf].mGraphicBuffer, item.mCrop);
381bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (image == EGL_NO_IMAGE_KHR) {
382ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
383bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                  mEglDisplay, buf);
38487a678478005026d950bedec49ee80b693777b95Andy McFadden            const sp<GraphicBuffer>& gb = mSlots[buf].mGraphicBuffer;
38587a678478005026d950bedec49ee80b693777b95Andy McFadden            ST_LOGW("buffer size=%ux%u st=%u usage=0x%x fmt=%d",
38687a678478005026d950bedec49ee80b693777b95Andy McFadden                gb->getWidth(), gb->getHeight(), gb->getStride(),
38787a678478005026d950bedec49ee80b693777b95Andy McFadden                gb->getUsage(), gb->getPixelFormat());
38887a678478005026d950bedec49ee80b693777b95Andy McFadden            releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
38987a678478005026d950bedec49ee80b693777b95Andy McFadden                    mEglDisplay, EGL_NO_SYNC_KHR);
390bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
391bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
392bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        mEglSlots[buf].mEglImage = image;
393dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        mEglSlots[buf].mCropRect = item.mCrop;
394ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
395ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
396bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
397bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = syncForReleaseLocked(mEglDisplay);
398bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
399bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // Release the buffer we just acquired.  It's not safe to
400bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // release the old buffer, so instead we just drop the new frame.
401c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // As we are still under lock since acquireBuffer, it is safe to
402c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // release by slot.
403c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
404c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mEglDisplay, EGL_NO_SYNC_KHR);
405bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
406bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
407ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
408ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
409bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture,
410bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
411bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            buf, mSlots[buf].mGraphicBuffer->handle);
412eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
413bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
414bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
415c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t status = releaseBufferLocked(
416c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mCurrentTexture, mCurrentTextureBuf, mEglDisplay,
417bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                mEglSlots[mCurrentTexture].mEglFence);
418ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (status < NO_ERROR) {
419ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
420bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                   strerror(-status), status);
421bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = status;
422bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // keep going, with error raised [?]
4232c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
424bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
4252c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
4262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // Update the GLConsumer state.
427bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTexture = buf;
428bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
429bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
430bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
431bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
432bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
433bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
434d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    mCurrentFrameNumber = item.mFrameNumber;
435bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
436bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
437bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
438bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
439bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
440bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
4412adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindTextureImageLocked() {
442bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
443bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
444bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
445bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
446bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
447bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
448bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
449bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
450bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
451bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
452bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
453bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
454bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (mCurrentTextureBuf == NULL) {
455bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: no currently-bound texture");
456bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return NO_INIT;
4578ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
45897eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        status_t err = bindUnslottedBufferLocked(mEglDisplay);
45997eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        if (err != NO_ERROR) {
46097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden            return err;
46197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden        }
462bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    } else {
463bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
4640eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
4659fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
46674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
4679fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
468bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            ST_LOGE("bindTextureImage: error binding external texture image %p"
469bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                    ": %#04x", image, error);
470bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            return UNKNOWN_ERROR;
4718ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
472bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
47397eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
47497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
47597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
47697eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
477bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
4789a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
47945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopianstatus_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
480bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
481bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
48286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
48345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (!contextCheck) {
48445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // if this is the first time we're called, mEglDisplay/mEglContext have
48545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // never been set, so don't error out (below).
48645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mEglDisplay == EGL_NO_DISPLAY) {
48745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            mEglDisplay = dpy;
48845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
48945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mEglContext == EGL_NO_DISPLAY) {
49045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            mEglContext = ctx;
49145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
49245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    }
49345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian
49445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
495bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
496bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
497bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
498b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
49945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
500bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
501bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
5028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
50350c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
504bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
505bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
506bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
5078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
5088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
50913f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hallvoid GLConsumer::setReleaseFence(const sp<Fence>& fence) {
51013f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall    if (fence->isValid() &&
51113f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
512c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t err = addReleaseFence(mCurrentTexture,
513c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mCurrentTextureBuf, fence);
51413f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        if (err != OK) {
51513f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
51613f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall                    strerror(-err), err);
51713f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        }
518ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
519ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
520ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
5212adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::detachFromContext() {
52274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
52374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("detachFromContext");
52474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
52574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
52674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
5272adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: abandoned GLConsumer");
52874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
52974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
53074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
53174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
5322adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("detachFromContext: GLConsumer is not attached to a "
53374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
53474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
53574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
53674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
53774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
53874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
53974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
54074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
54174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLDisplay");
54274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
54374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
54474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
54574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
54674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("detachFromContext: invalid current EGLContext");
54774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
54874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
54974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
55074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
55174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
55274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
55374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
55474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
55574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
55674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
55774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
55874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5599aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // Because we're giving up the EGLDisplay we need to free all the EGLImages
5609aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // that are associated with it.  They'll be recreated when the
5612adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // GLConsumer gets attached to a new OpenGL ES context (and thus gets a
5629aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    // new EGLDisplay).
5639aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
5649fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        EGLImageKHR img = mEglSlots[i].mEglImage;
5655c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        if (img != EGL_NO_IMAGE_KHR) {
5669aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis            eglDestroyImageKHR(mEglDisplay, img);
5679fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
5689aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        }
5699aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    }
5709aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis
57174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
57274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
57374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
57474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
57574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
57674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
57774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5783f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianstatus_t GLConsumer::attachToContext(uint32_t tex) {
57974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
58074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("attachToContext");
58174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
58274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
5842adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: abandoned GLConsumer");
58574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
58674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
58774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
5892adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("attachToContext: GLConsumer is already attached to a "
59074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
59174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
59274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
59374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
59474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
59574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
59674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
59774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
59874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLDisplay");
59974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
60074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
60174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
60274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
60374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        ST_LOGE("attachToContext: invalid current EGLContext");
60474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
60574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
60674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
60774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
60874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
6093f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    glBindTexture(mTexTarget, GLuint(tex));
61074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
61174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mCurrentTextureBuf != NULL) {
6125c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // The EGLImageKHR that was associated with the slot was destroyed when
6132adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        // the GLConsumer was detached from the old context, so we need to
6145c8a608497f12ecea4d6e8f1f286baf57c161ea3Jamie Gennis        // recreate it here.
615bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        status_t err = bindUnslottedBufferLocked(dpy);
616bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err != NO_ERROR) {
61774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
61874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
61974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
62074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
62274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
62374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
62474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
62574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
62774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
62874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
6292adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) {
630bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
631bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            mCurrentTexture, mCurrentTextureBuf.get());
632bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
633bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Create a temporary EGLImageKHR.
634dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    Rect crop;
635dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf, mCurrentCrop);
636bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (image == EGL_NO_IMAGE_KHR) {
637bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return UNKNOWN_ERROR;
638bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
639bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
640bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Attach the current buffer to the GL texture.
641bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
642bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
643bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    GLint error;
644bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = OK;
645bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
646bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
647bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                "(slot %d): %#04x", image, mCurrentTexture, error);
648bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        err = UNKNOWN_ERROR;
649bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
650bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
651bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We destroy the EGLImageKHR here because the current buffer may no
652bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // longer be associated with one of the buffer slots, so we have
653bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // nowhere to to store it.  If the buffer is still associated with a
654bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // slot then another EGLImageKHR will be created next time that buffer
655bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // gets acquired in updateTexImage.
656bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    eglDestroyImageKHR(dpy, image);
657bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
658bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
659bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
660bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
661bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
6622adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
66374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ST_LOGV("syncForReleaseLocked");
66474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
66501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
666ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useNativeFenceSync()) {
66701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
66801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
66901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
67001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
67101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
67274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
67374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
67401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
67501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
67698ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
67701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
67801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
67901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
68001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
68101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
68201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
683c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            status_t err = addReleaseFenceLocked(mCurrentTexture,
684c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                    mCurrentTextureBuf, fence);
68501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
68601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error adding release fence: "
68701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
68801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
68901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
690ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
69101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
69201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
69301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
69401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
69501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
69601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
69701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
69801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
69901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: error waiting for previous "
70001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
70101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
70201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
70301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
70401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
70501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
70601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
70701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
70801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
70974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
71001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
71101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
71201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
71301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
71401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
71501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
71601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
71701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
71801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
71901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
72074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
72174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
72274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
72374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
72474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
72574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
7262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenbool GLConsumer::isExternalFormat(uint32_t format)
7277a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
7287a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
7297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
7307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
7317a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
7327a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
7337a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
7347a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
7357a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7367a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
7377a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7387a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
7397a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
7407a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7417a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7427a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
7437a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7447a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7453f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianuint32_t GLConsumer::getCurrentTextureTarget() const {
746fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
7477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7487a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::getTransformMatrix(float mtx[16]) {
750f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
751736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
752736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
753736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
7542adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setFilteringEnabled(bool enabled) {
7555c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
756e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
7572adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden        ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
758e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
759e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
7605c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
7615c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
762e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
763e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf==NULL) {
764e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
765e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
766e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
767e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (needsRecompute && mCurrentTextureBuf != NULL) {
768e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
7695c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
7705c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
7715c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
7722adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::computeCurrentTransformMatrixLocked() {
773e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    ST_LOGV("computeCurrentTransformMatrixLocked");
774f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
775a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
776a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
777a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
778a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
779a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
780a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
781a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
782a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
783a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
784a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
785a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
786a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
787a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
788a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
789a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
790a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
791a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
792a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
793a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
794a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
795a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
796a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
797a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
798a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
799f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
800f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
801eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
802e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
803e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (buf == NULL) {
804e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
805e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
806e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
807dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    float mtxBeforeFlipV[16];
808dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    if (!isEglImageCroppable(mCurrentCrop)) {
809dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        Rect cropRect = mCurrentCrop;
810dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
811dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float bufferWidth = buf->getWidth();
812dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float bufferHeight = buf->getHeight();
813dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        if (!cropRect.isEmpty()) {
814dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            float shrinkAmount = 0.0f;
815dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            if (mFilteringEnabled) {
816dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // In order to prevent bilinear sampling beyond the edge of the
817dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // crop rectangle we may need to shrink it by 2 texels in each
818dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // dimension.  Normally this would just need to take 1/2 a texel
819dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // off each end, but because the chroma channels of YUV420 images
820dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // are subsampled we may need to shrink the crop region by a whole
821dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // texel on each side.
822dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                switch (buf->getPixelFormat()) {
823dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGBA_8888:
824dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGBX_8888:
825dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGB_888:
826dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGB_565:
827dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_BGRA_8888:
828dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // We know there's no subsampling of any channels, so we
829dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // only need to shrink by a half a pixel.
830dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        shrinkAmount = 0.5;
831dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        break;
832dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
833dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    default:
834dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // If we don't recognize the format, we must assume the
835dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // worst case (that we care about), which is YUV420.
836dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        shrinkAmount = 1.0;
837dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        break;
838dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                }
8395c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
8405c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
841dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // Only shrink the dimensions that are not the size of the buffer.
842dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            if (cropRect.width() < bufferWidth) {
843dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
844dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
845dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        bufferWidth;
846dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            }
847dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            if (cropRect.height() < bufferHeight) {
848dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
849dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        bufferHeight;
850dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
851dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        bufferHeight;
852dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            }
8535c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
854dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float crop[16] = {
855dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            sx, 0, 0, 0,
856dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            0, sy, 0, 0,
857dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            0, 0, 1, 0,
858dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            tx, ty, 0, 1,
859dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        };
860dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
861dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        mtxMul(mtxBeforeFlipV, crop, xform);
862dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    } else {
863dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        for (int i = 0; i < 16; i++) {
864dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            mtxBeforeFlipV[i] = xform[i];
8655c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
866a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
867a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
868a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
8692adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // coordinate of 0, so GLConsumer must behave the same way.  We don't
870a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
871a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
872736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
873f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
874f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
8752adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddennsecs_t GLConsumer::getTimestamp() {
8766ee96ad6a3da260f2473f78ea0582fd0970cf156Jamie Gennis    ST_LOGV("getTimestamp");
8771d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
8781d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
8791d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
8801d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
881d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvalansecs_t GLConsumer::getFrameNumber() {
882d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    ST_LOGV("getFrameNumber");
883d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    Mutex::Autolock lock(mMutex);
884d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    return mCurrentFrameNumber;
885d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala}
886d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala
8872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenEGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
888dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
8898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
8908ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
891dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
892dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
893dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
894dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
895dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
8968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
8978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
898dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    if (!crop.isValid()) {
899dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        // No crop rect to set, so terminate the attrib array before the crop.
900dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        attrs[2] = EGL_NONE;
901dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    } else if (!isEglImageCroppable(crop)) {
902dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        // The crop rect is not at the origin, so we can't set the crop on the
903dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
904dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        // extension.  In the future we can add a layered extension that
905dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        // removes this restriction if there is hardware that can support it.
906dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        attrs[2] = EGL_NONE;
907dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    }
9088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
9098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
9103cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
9113cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
912fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis        ST_LOGE("error creating EGLImage: %#x", error);
9138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
9148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
9158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
9168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
9172adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
9187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
9197a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
9207a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9217a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9222adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenRect GLConsumer::getCurrentCrop() const {
9237a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
924016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
925016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
926016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
927016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newWidth = mCurrentCrop.width();
928016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        int32_t newHeight = mCurrentCrop.height();
929016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
930016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
931016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
932016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too wide: newWidth = %d", newWidth);
933016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
934016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
935016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            ST_LOGV("too tall: newHeight = %d", newHeight);
936016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
937016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
938016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
939016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth < mCurrentCrop.width()) {
940016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dw = (newWidth - mCurrentCrop.width())/2;
941016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
942016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
943016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
944016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newHeight < mCurrentCrop.height()) {
945016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            int32_t dh = (newHeight - mCurrentCrop.height())/2;
946016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
947016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
948016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
949016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
950016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
951016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
952016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
953016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
954016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
955016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
9567a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9577a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9582adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentTransform() const {
9597a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
9607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
9617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9627a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9632adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentScalingMode() const {
9647734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
9657734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
9667734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
9677734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
9682adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<Fence> GLConsumer::getCurrentFence() const {
969dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
970dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
971dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
972dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
9732adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWait() const {
97461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
9753941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
9763941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
9773941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
9782adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWaitLocked() const {
97961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
98061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
98161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
98261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
98361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
98461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
98561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
98661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
98761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
98861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
98961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        ST_LOGE("doGLFenceWait: invalid current EGLContext");
99061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
99161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
99261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
9931df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (mCurrentFence->isValid()) {
994ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useWaitSync()) {
99561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
99661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
99761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
99861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
99961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
100061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
100161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
100261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
100361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
100461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
100561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
100661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
100761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
100861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
100961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
101061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
101161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
101261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
101361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
101461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
101561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
101661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
10172bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            eglWaitSyncKHR(dpy, sync, 0);
101861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
101961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
102061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
102161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
102261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
102361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
102461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
102561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
1026ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopian            status_t err = mCurrentFence->waitForever(
10272adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    "GLConsumer::doGLFenceWaitLocked");
102861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
102961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
103061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
103161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
103261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
103361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
103461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
103561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
103661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
103761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
10382adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::freeBufferLocked(int slotIndex) {
1039fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
10409abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
10419abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
10429abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
10439fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
10449aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis    if (img != EGL_NO_IMAGE_KHR) {
10459aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
10469aa74dbc7070aa396bc425ea3feae3d26e5393f6Jamie Gennis        eglDestroyImageKHR(mEglDisplay, img);
1047fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis    }
10489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
10499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
1050fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
1051fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
10522adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::abandonLocked() {
10539fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ST_LOGV("abandonLocked");
10549fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    mCurrentTextureBuf.clear();
10559fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
10567b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
10577b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
10582adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setName(const String8& name) {
1059eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
1060fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
1061db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerName(name);
1062b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1063b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
10642adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
1065b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
1066db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferFormat(defaultFormat);
1067b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1068b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
10692adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
1070b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
107185b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
1072db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setConsumerUsageBits(usage);
1073b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1074b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
10752adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setTransformHint(uint32_t hint) {
1076b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
1077db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setTransformHint(hint);
1078b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1079b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
108074d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid GLConsumer::dumpLocked(String8& result, const char* prefix) const
108168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
108274d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
10839fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
10849fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
10859fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
10869fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
10879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
108868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
108974d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    ConsumerBase::dumpLocked(result, prefix);
109068c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
109168c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
1092f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
1093f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1094f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1095f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1096f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1097f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1098f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1099f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1100f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1101f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1102f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1103f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1104f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1105f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1106f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1107f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1108f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1109f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1110f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1111f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1112f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
1113f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
11148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
1115