GLConsumer.cpp revision d723bd7669b4fc88dc282d8bf8ba5ecb2849d22f
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
50d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
51d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
52d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza//#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
53d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
54d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
5529b5762efc359022168e5099c1d17925444d3147Mathias Agopian
56ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatic const struct {
57d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    uint32_t width, height;
58ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    char const* bits;
5945263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian} kDebugData = { 15, 12,
60d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
61d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
62d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_____XX_XX_____"
63d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "__X_X_____X_X__"
64d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "__X_XXXXXXX_X__"
65d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "__XXXXXXXXXXX__"
66d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "___XX_XXX_XX___"
67d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "____XXXXXXX____"
68d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_____X___X_____"
69d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "____X_____X____"
70d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
71d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
7245263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian};
73ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
92f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
93f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
94f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
95f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
96f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
97f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
98f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
99f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
100f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
101f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1029870c9b66cc73ee31aabba23aa06deaf673ee5efMathias AgopianMutex GLConsumer::sStaticInitLock;
1039870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopiansp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
104fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
105dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool hasEglAndroidImageCropImpl() {
106dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
107dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
108dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    size_t cropExtLen = strlen(CROP_EXT_STR);
109dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    size_t extsLen = strlen(exts);
110dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool equal = !strcmp(CROP_EXT_STR, exts);
111dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
112dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool atEnd = (cropExtLen+1) < extsLen &&
113dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
114dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
115dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return equal || atStart || atEnd || inMiddle;
116dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
117dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
118dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool hasEglAndroidImageCrop() {
119dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    // Only compute whether the extension is present once the first time this
120dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    // function is called.
121dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    static bool hasIt = hasEglAndroidImageCropImpl();
122dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return hasIt;
123dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
124dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
125dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool isEglImageCroppable(const Rect& crop) {
126dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
127dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
128dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
1293f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
1303f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
131595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian    ConsumerBase(bq, isControlledByApp),
1321d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
133e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
1341df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    mCurrentFence(Fence::NO_FENCE),
1351d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
136d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    mCurrentFrameNumber(0),
137e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultWidth(1),
138e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultHeight(1),
1395c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
140b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
14186edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
142eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
143ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
144ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
14574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
14674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1476b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
148d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("GLConsumer");
149b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
150fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
151fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
152fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
153db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1548ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1558ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
156ab57491de3a89a2d454d3060d36adef71741a7aeDan StozaGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
157ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza        bool useFenceSync, bool isControlledByApp) :
158ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    ConsumerBase(bq, isControlledByApp),
159ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentTransform(0),
160ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
161ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentFence(Fence::NO_FENCE),
162ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentTimestamp(0),
163ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentFrameNumber(0),
164ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mDefaultWidth(1),
165ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mDefaultHeight(1),
166ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mFilteringEnabled(true),
167d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    mTexName(0),
168ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mUseFenceSync(useFenceSync),
169ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mTexTarget(texTarget),
170ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mEglDisplay(EGL_NO_DISPLAY),
171ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mEglContext(EGL_NO_CONTEXT),
172ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
173ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mAttached(false)
174ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza{
175d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("GLConsumer");
176ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza
177ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    memcpy(mCurrentTransformMatrix, mtxIdentity,
178ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza            sizeof(mCurrentTransformMatrix));
179ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza
180ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
181ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza}
182ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza
1832adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
1848072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian    Mutex::Autolock lock(mMutex);
185db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultMaxBufferCount(bufferCount);
1868072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian}
1878072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian
1888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1892adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
190a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
191b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
192016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
193016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
194db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferSize(w, h);
195a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
196a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1972adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::updateTexImage() {
198bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
199d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("updateTexImage");
200bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
201bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
202bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
203d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
204bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
205bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
206bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
207bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
208bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
209bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
210bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
211bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
212bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
213bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    BufferQueue::BufferItem item;
214bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
215bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
216bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
217bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
2181585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    err = acquireBufferLocked(&item, 0);
219bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
220bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
221bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
222d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGV("updateTexImage: no buffers were available");
223bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
224bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
225bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
226d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
227bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
228bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
229bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
230bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
231bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
232bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
233ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    err = updateAndReleaseLocked(item);
234bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
235bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
236bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
237bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
238bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
239bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
24097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
24197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
2422c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
2432c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
244ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
245ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::releaseTexImage() {
246ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ATRACE_CALL();
247d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("releaseTexImage");
248ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    Mutex::Autolock lock(mMutex);
249ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
250ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (mAbandoned) {
251d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
252ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        return NO_INIT;
253ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
254ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
255ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Make sure the EGL state is the same as in previous calls.
25645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    status_t err = NO_ERROR;
25745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian
25845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mAttached) {
25945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        err = checkAndUpdateEglStateLocked(true);
26045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (err != NO_ERROR) {
26145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            return err;
26245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
26345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    } else {
26445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // if we're detached, no need to validate EGL's state -- we won't use it.
265ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
266ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
267ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Update the GLConsumer state.
268ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    int buf = mCurrentTexture;
269ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
270ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
271d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
272ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
27345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mAttached) {
27445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // Do whatever sync ops we need to do before releasing the slot.
27545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            err = syncForReleaseLocked(mEglDisplay);
27645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            if (err != NO_ERROR) {
277d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
27845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian                return err;
27945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            }
28045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        } else {
28145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // if we're detached, we just use the fence that was created in detachFromContext()
28245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // so... basically, nothing more to do here.
283ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
284ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
28545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
286ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (err < NO_ERROR) {
287d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
288ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                    strerror(-err), err);
289ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            return err;
290ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
291ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
2925c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (mReleasedTexImage == NULL) {
2935c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
2945c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
2955c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
296ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
2975c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mCurrentTextureImage = mReleasedTexImage;
298ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentCrop.makeInvalid();
299ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTransform = 0;
300ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
301ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTimestamp = 0;
302ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentFence = Fence::NO_FENCE;
303ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
30445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mAttached) {
3055c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            // This binds a dummy buffer (mReleasedTexImage).
306d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            status_t result = bindTextureImageLocked();
307d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            if (result != NO_ERROR) {
308d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                return result;
3095c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            }
31045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        } else {
31145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // detached, don't touch the texture (and we may not even have an
31245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // EGLDisplay here.
31345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
314ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
315ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
316ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    return NO_ERROR;
317ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian}
318ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
3199870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopiansp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
3209870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    Mutex::Autolock _l(sStaticInitLock);
3219870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
3229870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        // The first time, create the debug texture in case the application
3239870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        // continues to use it.
3249870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        sp<GraphicBuffer> buffer = new GraphicBuffer(
3259870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian                kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
3269870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian                GraphicBuffer::USAGE_SW_WRITE_RARELY);
3279870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        uint32_t* bits;
3289870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
329d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t stride = buffer->getStride();
330d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t height = buffer->getHeight();
331d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        memset(bits, 0, stride * height * 4);
332d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        for (uint32_t y = 0; y < kDebugData.height; y++) {
333d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            for (uint32_t x = 0; x < kDebugData.width; x++) {
334d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
335d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                    0xFF000000 : 0xFFFFFFFF;
3369870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian            }
337d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            bits += stride;
3389870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        }
3399870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        buffer->unlock();
3409870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        sReleasedTexImageBuffer = buffer;
3419870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    }
3429870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    return sReleasedTexImageBuffer;
3439870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian}
3449870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian
3451585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFaddenstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
3461585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden        nsecs_t presentWhen) {
3471585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
3489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
3499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
3509fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
3519fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
3525c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // If item->mGraphicBuffer is not null, this buffer has not been acquired
3535c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // before, so any prior EglImage created is using a stale buffer. This
3545c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // replaces any old EglImage with a new one (using the new buffer).
3555c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (item->mGraphicBuffer != NULL) {
3565c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        int slot = item->mBuf;
3575c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
3589fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
3599fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
3609fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
3619fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
3629fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
363c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnarstatus_t GLConsumer::releaseBufferLocked(int buf,
364c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        sp<GraphicBuffer> graphicBuffer,
365c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        EGLDisplay display, EGLSyncKHR eglFence) {
366c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // release the buffer if it hasn't already been discarded by the
367c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // BufferQueue. This can happen, for example, when the producer of this
368c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // buffer has reallocated the original buffer slot after this buffer
369c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // was acquired.
370c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    status_t err = ConsumerBase::releaseBufferLocked(
371c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            buf, graphicBuffer, display, eglFence);
372d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
3739fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
3749fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
3759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
376ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
377bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
3789abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
3799abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
38087a678478005026d950bedec49ee80b693777b95Andy McFadden    int buf = item.mBuf;
38187a678478005026d950bedec49ee80b693777b95Andy McFadden
38274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
383d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
38474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
38587a678478005026d950bedec49ee80b693777b95Andy McFadden        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
38687a678478005026d950bedec49ee80b693777b95Andy McFadden                mEglDisplay, EGL_NO_SYNC_KHR);
38774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
38874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
38974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
390bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
391bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
392bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
39387a678478005026d950bedec49ee80b693777b95Andy McFadden        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
39487a678478005026d950bedec49ee80b693777b95Andy McFadden                mEglDisplay, EGL_NO_SYNC_KHR);
395bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
396ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
397ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
3985c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
3995c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // if nessessary, for the gralloc buffer currently in the slot in
4005c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // ConsumerBase.
401bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
4025c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // means the buffer was previously acquired).
4035c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
4045c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (err != NO_ERROR) {
405d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
4065c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mEglDisplay, buf);
4075c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
4085c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mEglDisplay, EGL_NO_SYNC_KHR);
4095c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return UNKNOWN_ERROR;
410ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
411ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
412bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
413bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = syncForReleaseLocked(mEglDisplay);
414bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
415bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // Release the buffer we just acquired.  It's not safe to
416bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // release the old buffer, so instead we just drop the new frame.
417c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // As we are still under lock since acquireBuffer, it is safe to
418c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        // release by slot.
419c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
420c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar                mEglDisplay, EGL_NO_SYNC_KHR);
421bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
422bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
423ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
424d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
4255c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            mCurrentTexture, mCurrentTextureImage != NULL ?
4265c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                    mCurrentTextureImage->graphicBufferHandle() : 0,
427bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            buf, mSlots[buf].mGraphicBuffer->handle);
428eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
429bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
430bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
431c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t status = releaseBufferLocked(
4325c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
4335c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
434ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (status < NO_ERROR) {
435d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
436bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                   strerror(-status), status);
437bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = status;
438bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // keep going, with error raised [?]
4392c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
440bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
4412c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
4422adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // Update the GLConsumer state.
443bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTexture = buf;
4445c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mCurrentTextureImage = mEglSlots[buf].mEglImage;
445bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
446bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
447bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
448bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
449bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
450d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    mCurrentFrameNumber = item.mFrameNumber;
451bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
452bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
453bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
454bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
455bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
456bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
4572adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindTextureImageLocked() {
458bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
459bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
460bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
461bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
462bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
463d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLenum error;
464bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
465d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
466bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
467bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
468bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
4695c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
4705c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            mCurrentTextureImage == NULL) {
471d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("bindTextureImage: no currently-bound texture");
4725c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return NO_INIT;
4735c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
4740eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
4755c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
4762d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                                                        mCurrentCrop);
4775c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (err != NO_ERROR) {
478d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
4795c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mEglDisplay, mCurrentTexture);
4805c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return UNKNOWN_ERROR;
4815c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
4825c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mCurrentTextureImage->bindToTextureTarget(mTexTarget);
4835c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
4842d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // In the rare case that the display is terminated and then initialized
4852d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // again, we can't detect that the display changed (it didn't), but the
4862d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // image is invalid. In this case, repeat the exact same steps while
4872d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // forcing the creation of a new image.
4882d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    if ((error = glGetError()) != GL_NO_ERROR) {
4892d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        glBindTexture(mTexTarget, mTexName);
490d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay,
491d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                                                               mCurrentCrop,
492d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                                                               true);
493d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        if (result != NO_ERROR) {
494d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
4952d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                    mEglDisplay, mCurrentTexture);
4962d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner            return UNKNOWN_ERROR;
4972d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        }
4982d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
4992d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        if ((error = glGetError()) != GL_NO_ERROR) {
500d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
5012d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner            return UNKNOWN_ERROR;
5022d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        }
503bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
50497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
50597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
50697eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
507bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
5089a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
50945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopianstatus_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
510bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
511bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
51286edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
51345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (!contextCheck) {
51445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // if this is the first time we're called, mEglDisplay/mEglContext have
51545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // never been set, so don't error out (below).
51645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mEglDisplay == EGL_NO_DISPLAY) {
51745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            mEglDisplay = dpy;
51845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
51946a1f6b40e1f7677cd41cd30f729ff66c7c21517Jesse Hall        if (mEglContext == EGL_NO_CONTEXT) {
52045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            mEglContext = ctx;
52145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
52245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    }
52345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian
52445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
525d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
526bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
527bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
528b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
52945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
530d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
531bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
5328ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
53350c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
534bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
535bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
536bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
5378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
5388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
53913f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hallvoid GLConsumer::setReleaseFence(const sp<Fence>& fence) {
54013f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall    if (fence->isValid() &&
54113f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
542c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t err = addReleaseFence(mCurrentTexture,
5435c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mCurrentTextureImage->graphicBuffer(), fence);
54413f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        if (err != OK) {
545d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
54613f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall                    strerror(-err), err);
54713f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        }
548ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
549ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
550ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
5512adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::detachFromContext() {
55274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
553d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("detachFromContext");
55474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
55574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
55674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
557d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: abandoned GLConsumer");
55874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
55974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
56074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
56174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
562d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
56374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
56474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
56574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
56674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
56774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
56874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
56974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
57074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
571d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: invalid current EGLDisplay");
57274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
57374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
57474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
57574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
576d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: invalid current EGLContext");
57774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
57874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
57974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
58174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
58274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
58374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
58474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
58574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
58774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
58874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
58974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
59074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
59174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
59274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
59374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
59474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
59574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
5963f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianstatus_t GLConsumer::attachToContext(uint32_t tex) {
59774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
598d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("attachToContext");
59974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
60074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
60174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
602d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: abandoned GLConsumer");
60374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
60474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
60574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
60674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
607d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: GLConsumer is already attached to a "
60874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
60974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
61074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
61174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
61274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
61374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
61474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
61574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
616d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: invalid current EGLDisplay");
61774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
61874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
61974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
621d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: invalid current EGLContext");
62274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
62374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
62474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
62674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
6273f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    glBindTexture(mTexTarget, GLuint(tex));
62874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
63074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
63174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
63274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
63374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
6345c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mCurrentTextureImage != NULL) {
6355c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // This may wait for a buffer a second time. This is likely required if
6365c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // this is a different context, since otherwise the wait could be skipped
6375c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // by bouncing through another context. For the same context the extra
6385c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // wait is redundant.
6395c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        status_t err =  bindTextureImageLocked();
6405c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (err != NO_ERROR) {
6415c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            return err;
6425c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
643bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
644bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
6455c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return OK;
646bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
647bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
648bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
6492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
650d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("syncForReleaseLocked");
65174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
65201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
653ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useNativeFenceSync()) {
65401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
65501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
65601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
657d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
65801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
65974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
66074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
66101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
66201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
66398ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
66401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
665d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
66601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
66701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
66801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
66901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
670c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            status_t err = addReleaseFenceLocked(mCurrentTexture,
6715c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                    mCurrentTextureImage->graphicBuffer(), fence);
67201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
673d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error adding release fence: "
67401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
67501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
67601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
677ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
67801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
67901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
68001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
68101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
68201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
68301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
68401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
68501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
686d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                    GLC_LOGE("syncForReleaseLocked: error waiting for previous "
68701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
68801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
68901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
690d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                    GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
69101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
69201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
69301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
69401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
69501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
69674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
69701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
69801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
69901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
70001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
701d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
70201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
70301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
70401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
70501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
70601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
70774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
70874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
70974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
71074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
71174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
71274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
713d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stozabool GLConsumer::isExternalFormat(PixelFormat format)
7147a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
7157a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
7167a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
7177a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
7187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
7197a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
7207a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
7217a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
7227a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7237a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
7247a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7257a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
7267a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
7277a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7287a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
7307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7317a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7323f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianuint32_t GLConsumer::getCurrentTextureTarget() const {
733fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
7347a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7357a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7362adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::getTransformMatrix(float mtx[16]) {
737f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
738736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
739736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
740736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
7412adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setFilteringEnabled(bool enabled) {
7425c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
743e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
744d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
745e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
746e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
7475c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
7485c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
749e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
7505c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (needsRecompute && mCurrentTextureImage==NULL) {
751d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
752e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
753e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
7545c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (needsRecompute && mCurrentTextureImage != NULL) {
755e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
7565c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
7575c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
7585c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
7592adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::computeCurrentTransformMatrixLocked() {
760d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("computeCurrentTransformMatrixLocked");
761f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
762a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
763a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
764a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
765a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
766a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
767a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
768a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
769a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
770a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
771a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
772a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
773a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
774a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
775a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
776a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
777a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
778a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
779a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
780a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
781a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
782a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
783a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
784a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
785a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
786f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
787f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
7885c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    sp<GraphicBuffer> buf = (mCurrentTextureImage == NULL) ?
7895c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            NULL : mCurrentTextureImage->graphicBuffer();
790e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
791e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (buf == NULL) {
792d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL");
793e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
794e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
795dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    float mtxBeforeFlipV[16];
796dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    if (!isEglImageCroppable(mCurrentCrop)) {
797dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        Rect cropRect = mCurrentCrop;
798dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
799dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float bufferWidth = buf->getWidth();
800dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float bufferHeight = buf->getHeight();
801dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        if (!cropRect.isEmpty()) {
802dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            float shrinkAmount = 0.0f;
803dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            if (mFilteringEnabled) {
804dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // In order to prevent bilinear sampling beyond the edge of the
805dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // crop rectangle we may need to shrink it by 2 texels in each
806dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // dimension.  Normally this would just need to take 1/2 a texel
807dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // off each end, but because the chroma channels of YUV420 images
808dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // are subsampled we may need to shrink the crop region by a whole
809dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                // texel on each side.
810dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                switch (buf->getPixelFormat()) {
811dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGBA_8888:
812dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGBX_8888:
813dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGB_888:
814dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_RGB_565:
815dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    case PIXEL_FORMAT_BGRA_8888:
816dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // We know there's no subsampling of any channels, so we
817dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // only need to shrink by a half a pixel.
818dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        shrinkAmount = 0.5;
819dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        break;
820dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
821dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                    default:
822dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // If we don't recognize the format, we must assume the
823dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        // worst case (that we care about), which is YUV420.
824dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        shrinkAmount = 1.0;
825dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        break;
826dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                }
8275c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
8285c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
829dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            // Only shrink the dimensions that are not the size of the buffer.
830dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            if (cropRect.width() < bufferWidth) {
831dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
832dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
833dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        bufferWidth;
834dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            }
835dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            if (cropRect.height() < bufferHeight) {
836dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
837dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        bufferHeight;
838dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
839dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis                        bufferHeight;
840dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            }
8415c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
842dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float crop[16] = {
843dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            sx, 0, 0, 0,
844dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            0, sy, 0, 0,
845dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            0, 0, 1, 0,
846dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            tx, ty, 0, 1,
847dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        };
848dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
849dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        mtxMul(mtxBeforeFlipV, crop, xform);
850dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    } else {
851dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        for (int i = 0; i < 16; i++) {
852dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            mtxBeforeFlipV[i] = xform[i];
8535c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
854a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
855a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
856a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
8572adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // coordinate of 0, so GLConsumer must behave the same way.  We don't
858a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
859a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
860736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
861f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
862f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
8632adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddennsecs_t GLConsumer::getTimestamp() {
864d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("getTimestamp");
8651d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
8661d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
8671d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
8681d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
869d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stozauint64_t GLConsumer::getFrameNumber() {
870d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("getFrameNumber");
871d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    Mutex::Autolock lock(mMutex);
872d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    return mCurrentFrameNumber;
873d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala}
874d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala
8752adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
8767a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
8775c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return (mCurrentTextureImage == NULL) ?
8785c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            NULL : mCurrentTextureImage->graphicBuffer();
8797a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
8807a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
8812adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenRect GLConsumer::getCurrentCrop() const {
8827a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
883016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
884016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
885016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
886d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
887d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
888016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
889016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
890016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
891d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGV("too wide: newWidth = %d", newWidth);
892016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
893016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
894d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGV("too tall: newHeight = %d", newHeight);
895016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
896016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
897d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
898d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
899d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza
900016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
901d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        if (newWidth < currentWidth) {
902d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            uint32_t dw = (newWidth - currentWidth) / 2;
903016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left -=dw;
904016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right += dw;
905016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
906d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        } else if (newHeight < currentHeight) {
907d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            uint32_t dh = (newHeight - currentHeight) / 2;
908016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.top -= dh;
909016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.bottom += dh;
910016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
911016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
912d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
913016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
914016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
915016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
916016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
917016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
9187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9197a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9202adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentTransform() const {
9217a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
9227a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
9237a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9247a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9252adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentScalingMode() const {
9267734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
9277734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
9287734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
9297734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
9302adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<Fence> GLConsumer::getCurrentFence() const {
931dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
932dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
933dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
934dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
9352adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWait() const {
93661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
9373941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
9383941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
9393941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
9402adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWaitLocked() const {
94161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
94261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
94361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
94461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
94561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
946d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
94761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
94861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
94961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
95061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
951d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("doGLFenceWait: invalid current EGLContext");
95261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
95361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
95461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
9551df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (mCurrentFence->isValid()) {
956ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useWaitSync()) {
95761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
95861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
95961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
960d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
96161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
96261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
96361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
96461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
96561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
96661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
96761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
96861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
96961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
97061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
971d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
97261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
97361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
97461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
97561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
97661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
97761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
97861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
9792bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            eglWaitSyncKHR(dpy, sync, 0);
98061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
98161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
98261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
983d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
98461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
98561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
98661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
98761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
988ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopian            status_t err = mCurrentFence->waitForever(
9892adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    "GLConsumer::doGLFenceWaitLocked");
99061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
991d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
99261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
99361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
99461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
99561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
99661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
99761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
99861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
99961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
10002adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::freeBufferLocked(int slotIndex) {
1001d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
10029abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
10039abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
10049abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
10055c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mEglSlots[slotIndex].mEglImage.clear();
10069fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
1007fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
1008fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
10092adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::abandonLocked() {
1010d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("abandonLocked");
10115c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mCurrentTextureImage.clear();
10129fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
10137b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
10147b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
10152adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setName(const String8& name) {
1016eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
1017fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
1018db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerName(name);
1019b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1020b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
1021d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stozastatus_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
1022b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
1023db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferFormat(defaultFormat);
1024b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1025b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
10262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
1027b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
102885b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
1029db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setConsumerUsageBits(usage);
1030b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1031b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
10322adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setTransformHint(uint32_t hint) {
1033b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
1034db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setTransformHint(hint);
1035b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1036b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
103774d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid GLConsumer::dumpLocked(String8& result, const char* prefix) const
103868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
103974d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
10409fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
10419fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
10429fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
10439fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
10449fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
104568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
104674d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    ConsumerBase::dumpLocked(result, prefix);
104768c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
104868c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
1049f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
1050f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1051f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1052f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1053f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1054f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1055f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1056f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1057f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1058f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1059f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1060f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1061f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1062f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1063f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1064f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1065f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1066f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1067f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1068f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1069f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
1070f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
10715c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric PennerGLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
10725c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mGraphicBuffer(graphicBuffer),
10735c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mEglImage(EGL_NO_IMAGE_KHR),
10745c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mEglDisplay(EGL_NO_DISPLAY) {
10755c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
10765c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
10775c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric PennerGLConsumer::EglImage::~EglImage() {
10785c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mEglImage != EGL_NO_IMAGE_KHR) {
10795c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
10805c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner           ALOGE("~EglImage: eglDestroyImageKHR failed");
10815c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
108278be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine        eglTerminate(mEglDisplay);
10835c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
10845c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
10855c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
10865c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Pennerstatus_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
10872d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                                              const Rect& cropRect,
10882d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                                              bool forceCreation) {
10895c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // If there's an image and it's no longer valid, destroy it.
10905c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
10915c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    bool displayInvalid = mEglDisplay != eglDisplay;
10925c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
10932d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
10945c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
10955c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner           ALOGE("createIfNeeded: eglDestroyImageKHR failed");
10965c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
109778be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine        eglTerminate(mEglDisplay);
10985c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglImage = EGL_NO_IMAGE_KHR;
10995c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglDisplay = EGL_NO_DISPLAY;
11005c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
11015c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11025c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // If there's no image, create one.
11035c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mEglImage == EGL_NO_IMAGE_KHR) {
11045c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglDisplay = eglDisplay;
11055c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mCropRect = cropRect;
11065c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
11075c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
11085c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11095c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // Fail if we can't create a valid image.
11105c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mEglImage == EGL_NO_IMAGE_KHR) {
11115c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglDisplay = EGL_NO_DISPLAY;
11125c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mCropRect.makeInvalid();
11135c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        const sp<GraphicBuffer>& buffer = mGraphicBuffer;
11145c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
11155c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
11165c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            buffer->getUsage(), buffer->getPixelFormat());
11175c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return UNKNOWN_ERROR;
11185c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
11195c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11205c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return OK;
11215c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
11225c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11235c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Pennervoid GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1124d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    glEGLImageTargetTexture2DOES(texTarget,
1125d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            static_cast<GLeglImageOES>(mEglImage));
11265c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
11275c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11285c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric PennerEGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
11295c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
1130d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    EGLClientBuffer cbuf =
1131d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
11325c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    EGLint attrs[] = {
11335c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
11345c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
11355c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
11365c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
11375c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
11385c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_NONE,
11395c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    };
11405c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (!crop.isValid()) {
11415c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // No crop rect to set, so terminate the attrib array before the crop.
11425c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        attrs[2] = EGL_NONE;
11435c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    } else if (!isEglImageCroppable(crop)) {
11445c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // The crop rect is not at the origin, so we can't set the crop on the
11455c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
11465c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // extension.  In the future we can add a layered extension that
11475c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // removes this restriction if there is hardware that can support it.
11485c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        attrs[2] = EGL_NONE;
11495c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
115078be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine    eglInitialize(dpy, 0, 0);
11515c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
11525c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
11535c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (image == EGL_NO_IMAGE_KHR) {
11545c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGLint error = eglGetError();
11555c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        ALOGE("error creating EGLImage: %#x", error);
115678be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine        eglTerminate(dpy);
11575c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
11585c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return image;
11595c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
11605c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11618ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
1162