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
32dd26416fe135f93ef2c8570738f8e1ca5e2ca3a3Dan Stoza#include <gui/BufferItem.h>
33ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian#include <gui/GLConsumer.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"
46aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
47aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner#define EGL_PROTECTED_CONTENT_EXT 0x32C0
48dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
4997eba8904c2f221c42a9473407223a4c3a213f75Andy McFaddennamespace android {
5097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
512adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden// Macros for including the GLConsumer name in log messages
52d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
53d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
54d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza//#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
55d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
56d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza#define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
5729b5762efc359022168e5099c1d17925444d3147Mathias Agopian
58ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatic const struct {
59d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    uint32_t width, height;
60ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    char const* bits;
6145263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian} kDebugData = { 15, 12,
62d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
63d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
64d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_____XX_XX_____"
65d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "__X_X_____X_X__"
66d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "__X_XXXXXXX_X__"
67d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "__XXXXXXXXXXX__"
68d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "___XX_XXX_XX___"
69d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "____XXXXXXX____"
70d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_____X___X_____"
71d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "____X_____X____"
72d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
73d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    "_______________"
7445263e2475ac6a885dbd78eff7d4e44f374e5237Mathias Agopian};
75ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
80f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
81f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
82f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
83f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
84f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
85f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
86f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
87f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
88f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
89f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
90f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
91f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
92f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
93f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
94f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
95f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
96f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
97f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
98f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
99f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
100f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
101f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
102f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
103f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1049870c9b66cc73ee31aabba23aa06deaf673ee5efMathias AgopianMutex GLConsumer::sStaticInitLock;
1059870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopiansp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
106fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis
107dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool hasEglAndroidImageCropImpl() {
108dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
109dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
110dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    size_t cropExtLen = strlen(CROP_EXT_STR);
111dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    size_t extsLen = strlen(exts);
112dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool equal = !strcmp(CROP_EXT_STR, exts);
113dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
114dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool atEnd = (cropExtLen+1) < extsLen &&
115dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
116dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
117dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return equal || atStart || atEnd || inMiddle;
118dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
119dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
120dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool hasEglAndroidImageCrop() {
121dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    // Only compute whether the extension is present once the first time this
122dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    // function is called.
123dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    static bool hasIt = hasEglAndroidImageCropImpl();
124dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return hasIt;
125dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
126dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
127aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donnerstatic bool hasEglProtectedContentImpl() {
128aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
129aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
130aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
131aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    size_t extsLen = strlen(exts);
132aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
133aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
134aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    bool atEnd = (cropExtLen+1) < extsLen &&
135aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner            !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
136aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
1374df76b2f5f7e8be128b5ec7a2d8d03845effaea0Craig Donner    return equal || atStart || atEnd || inMiddle;
138aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner}
139aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner
140aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donnerstatic bool hasEglProtectedContent() {
141aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    // Only compute whether the extension is present once the first time this
142aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    // function is called.
143aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    static bool hasIt = hasEglProtectedContentImpl();
144aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    return hasIt;
145aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner}
146aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner
147dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennisstatic bool isEglImageCroppable(const Rect& crop) {
148dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
149dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis}
150dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
1513f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
1523f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
153595264f1af12e25dce57d7c5b1d52ed86ac0d0c9Mathias Agopian    ConsumerBase(bq, isControlledByApp),
15460d6922a011fe18c111b8d30fb6ef1f655b6b15ePablo Ceballos    mCurrentCrop(Rect::EMPTY_RECT),
1551d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
156e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
1571df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    mCurrentFence(Fence::NO_FENCE),
1581d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
159bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter    mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
160d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    mCurrentFrameNumber(0),
161e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultWidth(1),
162e692ab9a6be63193c5b52a6562d85d06c40463b8Mathias Agopian    mDefaultHeight(1),
1635c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled(true),
164b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian    mTexName(tex),
16586edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis    mUseFenceSync(useFenceSync),
166eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    mTexTarget(texTarget),
167ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglDisplay(EGL_NO_DISPLAY),
168ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    mEglContext(EGL_NO_CONTEXT),
16974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
17074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached(true)
1716b091c53000c843211c218ce40287a7edca9bc63Daniel Lam{
172d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("GLConsumer");
173b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
174fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    memcpy(mCurrentTransformMatrix, mtxIdentity,
175fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis            sizeof(mCurrentTransformMatrix));
176fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
177db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
1788ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
180ab57491de3a89a2d454d3060d36adef71741a7aeDan StozaGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
181ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza        bool useFenceSync, bool isControlledByApp) :
182ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    ConsumerBase(bq, isControlledByApp),
18360d6922a011fe18c111b8d30fb6ef1f655b6b15ePablo Ceballos    mCurrentCrop(Rect::EMPTY_RECT),
184ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentTransform(0),
185ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
186ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentFence(Fence::NO_FENCE),
187ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentTimestamp(0),
188bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter    mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
189ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentFrameNumber(0),
190ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mDefaultWidth(1),
191ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mDefaultHeight(1),
192ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mFilteringEnabled(true),
193d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    mTexName(0),
194ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mUseFenceSync(useFenceSync),
195ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mTexTarget(texTarget),
196ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mEglDisplay(EGL_NO_DISPLAY),
197ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mEglContext(EGL_NO_CONTEXT),
198ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
199ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mAttached(false)
200ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza{
201d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("GLConsumer");
202ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza
203ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    memcpy(mCurrentTransformMatrix, mtxIdentity,
204ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza            sizeof(mCurrentTransformMatrix));
205ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza
206ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
207ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza}
208ab57491de3a89a2d454d3060d36adef71741a7aeDan Stoza
2092adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
210a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
211b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
21265d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
21365d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
21465d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return NO_INIT;
21565d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
216016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultWidth = w;
217016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    mDefaultHeight = h;
218db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferSize(w, h);
219a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
220a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
2212adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::updateTexImage() {
222bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    ATRACE_CALL();
223d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("updateTexImage");
224bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    Mutex::Autolock lock(mMutex);
225bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
226bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mAbandoned) {
227d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
228bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return NO_INIT;
229bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
230bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
231bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Make sure the EGL state is the same as in previous calls.
232bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    status_t err = checkAndUpdateEglStateLocked();
233bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
234bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
235bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
236bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
237dd26416fe135f93ef2c8570738f8e1ca5e2ca3a3Dan Stoza    BufferItem item;
238bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
239bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Acquire the next buffer.
240bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // In asynchronous mode the list is guaranteed to be one buffer
241bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // deep, while in synchronous mode we use the oldest buffer.
2421585c4d9fbbba3ba70ae625923b85cd02cb8a0fdAndy McFadden    err = acquireBufferLocked(&item, 0);
243bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
244bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
245bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            // We always bind the texture even if we don't update its contents.
246d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGV("updateTexImage: no buffers were available");
247bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            glBindTexture(mTexTarget, mTexName);
248bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden            err = NO_ERROR;
249bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        } else {
250d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
251bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden                strerror(-err), err);
252bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        }
253bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
254bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
255bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
256bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Release the previous buffer.
257ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    err = updateAndReleaseLocked(item);
258bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
259bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        // We always bind the texture.
260bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        glBindTexture(mTexTarget, mTexName);
261bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
262bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
263bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
26497eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Bind the new buffer to the GL texture, and wait until it's ready.
26597eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return bindTextureImageLocked();
2662c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian}
2672c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
268ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
269ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopianstatus_t GLConsumer::releaseTexImage() {
270ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    ATRACE_CALL();
271d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("releaseTexImage");
272ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    Mutex::Autolock lock(mMutex);
273ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
274ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (mAbandoned) {
275d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
276ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        return NO_INIT;
277ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
278ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
279ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Make sure the EGL state is the same as in previous calls.
28045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    status_t err = NO_ERROR;
28145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian
28245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mAttached) {
28345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        err = checkAndUpdateEglStateLocked(true);
28445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (err != NO_ERROR) {
28545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            return err;
28645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
28745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    } else {
28845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // if we're detached, no need to validate EGL's state -- we won't use it.
289ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
290ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
291ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    // Update the GLConsumer state.
292ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    int buf = mCurrentTexture;
293ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
294ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
295d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
296ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
29745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mAttached) {
29845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // Do whatever sync ops we need to do before releasing the slot.
29945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            err = syncForReleaseLocked(mEglDisplay);
30045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            if (err != NO_ERROR) {
301d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
30245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian                return err;
30345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            }
30445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        } else {
30545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // if we're detached, we just use the fence that was created in detachFromContext()
30645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // so... basically, nothing more to do here.
307ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
308ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
30945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
310ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        if (err < NO_ERROR) {
311d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
312ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian                    strerror(-err), err);
313ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian            return err;
314ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        }
315ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
3165c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (mReleasedTexImage == NULL) {
3175c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
3185c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
3195c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
320ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
3215c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mCurrentTextureImage = mReleasedTexImage;
322ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentCrop.makeInvalid();
323ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTransform = 0;
324ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentTimestamp = 0;
325bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter        mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
326ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian        mCurrentFence = Fence::NO_FENCE;
3273d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Anderson        mCurrentFenceTime = FenceTime::NO_FENCE;
328ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
32945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mAttached) {
3305c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            // This binds a dummy buffer (mReleasedTexImage).
331d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            status_t result = bindTextureImageLocked();
332d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            if (result != NO_ERROR) {
333d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                return result;
3345c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            }
33545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        } else {
33645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // detached, don't touch the texture (and we may not even have an
33745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            // EGLDisplay here.
33845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
339ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    }
340ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
341ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian    return NO_ERROR;
342ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian}
343ad678e18b66f495efa78dc3b9ab99b579945c9e2Mathias Agopian
3449870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopiansp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
3459870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    Mutex::Autolock _l(sStaticInitLock);
3469870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
3479870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        // The first time, create the debug texture in case the application
3489870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        // continues to use it.
3499870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        sp<GraphicBuffer> buffer = new GraphicBuffer(
3509870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian                kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
351d4079aff759713e7c7dd14cecb585a7290e80772Dan Stoza                GraphicBuffer::USAGE_SW_WRITE_RARELY,
352d4079aff759713e7c7dd14cecb585a7290e80772Dan Stoza                "[GLConsumer debug texture]");
3539870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        uint32_t* bits;
3549870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
355d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t stride = buffer->getStride();
356d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t height = buffer->getHeight();
357d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        memset(bits, 0, stride * height * 4);
358d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        for (uint32_t y = 0; y < kDebugData.height; y++) {
359d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            for (uint32_t x = 0; x < kDebugData.width; x++) {
360d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
361d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                    0xFF000000 : 0xFFFFFFFF;
3629870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian            }
363d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            bits += stride;
3649870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        }
3659870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        buffer->unlock();
3669870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian        sReleasedTexImageBuffer = buffer;
3679870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    }
3689870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian    return sReleasedTexImageBuffer;
3699870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian}
3709870c9b66cc73ee31aabba23aa06deaf673ee5efMathias Agopian
371dd26416fe135f93ef2c8570738f8e1ca5e2ca3a3Dan Stozastatus_t GLConsumer::acquireBufferLocked(BufferItem *item,
372a4650a50a0b35e9e4342d6600b6eb24fd94bb8e5Dan Stoza        nsecs_t presentWhen, uint64_t maxFrameNumber) {
373a4650a50a0b35e9e4342d6600b6eb24fd94bb8e5Dan Stoza    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
374a4650a50a0b35e9e4342d6600b6eb24fd94bb8e5Dan Stoza            maxFrameNumber);
3759fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    if (err != NO_ERROR) {
3769fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis        return err;
3779fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
3789fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
3795c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // If item->mGraphicBuffer is not null, this buffer has not been acquired
3805c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // before, so any prior EglImage created is using a stale buffer. This
3815c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // replaces any old EglImage with a new one (using the new buffer).
3825c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (item->mGraphicBuffer != NULL) {
38347650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos        int slot = item->mSlot;
3845c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
3859fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    }
3869fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
3879fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return NO_ERROR;
3889fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
3899fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
390c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnarstatus_t GLConsumer::releaseBufferLocked(int buf,
391c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        sp<GraphicBuffer> graphicBuffer,
392c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        EGLDisplay display, EGLSyncKHR eglFence) {
393c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // release the buffer if it hasn't already been discarded by the
394c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // BufferQueue. This can happen, for example, when the producer of this
395c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // buffer has reallocated the original buffer slot after this buffer
396c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    // was acquired.
397c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar    status_t err = ConsumerBase::releaseBufferLocked(
398c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            buf, graphicBuffer, display, eglFence);
399d1b330de416adff0d178a5cb7271419d9ed7a89aJamie Gennis    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
4009fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    return err;
4019fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis}
4029fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis
4033ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stozastatus_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
4043ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza        PendingRelease* pendingRelease)
405bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden{
4069abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    status_t err = NO_ERROR;
4079abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam
40847650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos    int slot = item.mSlot;
40987a678478005026d950bedec49ee80b693777b95Andy McFadden
41074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
411d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
41274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "ES context");
41347650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
41487a678478005026d950bedec49ee80b693777b95Andy McFadden                mEglDisplay, EGL_NO_SYNC_KHR);
41574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
41674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
41774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
418bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Confirm state.
419bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    err = checkAndUpdateEglStateLocked();
420bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (err != NO_ERROR) {
42147650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
42287a678478005026d950bedec49ee80b693777b95Andy McFadden                mEglDisplay, EGL_NO_SYNC_KHR);
423bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return err;
424ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
425ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
4265c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
4275c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // if nessessary, for the gralloc buffer currently in the slot in
4285c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // ConsumerBase.
429bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // We may have to do this even when item.mGraphicBuffer == NULL (which
4305c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // means the buffer was previously acquired).
43147650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos    err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
4325c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (err != NO_ERROR) {
433d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
43447650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos                mEglDisplay, slot);
43547650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
4365c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mEglDisplay, EGL_NO_SYNC_KHR);
4375c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return UNKNOWN_ERROR;
438ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis    }
439ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
440bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // Do whatever sync ops we need to do before releasing the old slot.
441ff95aabbcc6e8606acbd7933c90eeb9b8b382a21Pablo Ceballos    if (slot != mCurrentTexture) {
44233fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos        err = syncForReleaseLocked(mEglDisplay);
44333fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos        if (err != NO_ERROR) {
44433fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos            // Release the buffer we just acquired.  It's not safe to
44533fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos            // release the old buffer, so instead we just drop the new frame.
44633fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos            // As we are still under lock since acquireBuffer, it is safe to
44733fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos            // release by slot.
44833fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos            releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
44933fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos                    mEglDisplay, EGL_NO_SYNC_KHR);
45033fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos            return err;
45133fcc2ecf707bfa15360d6d3ec95c778423d3032Pablo Ceballos        }
452bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
453ce561372186c7549a8a5fe996ac5965cda087007Jamie Gennis
454d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
4555c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            mCurrentTexture, mCurrentTextureImage != NULL ?
4565c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                    mCurrentTextureImage->graphicBufferHandle() : 0,
45747650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos            slot, mSlots[slot].mGraphicBuffer->handle);
458eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam
459ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584Pablo Ceballos    // Hang onto the pointer so that it isn't freed in the call to
4603559fbf93801e2c0d9d8fb246fb9b867a361b464Pablo Ceballos    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
461ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584Pablo Ceballos    // the same.
462ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584Pablo Ceballos    sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
463ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584Pablo Ceballos
464bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    // release old buffer
465bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
4663ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza        if (pendingRelease == nullptr) {
4673ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            status_t status = releaseBufferLocked(
4683ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                    mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
4693ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                    mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
4703ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            if (status < NO_ERROR) {
4713ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
4723ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                        strerror(-status), status);
4733ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                err = status;
4743ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                // keep going, with error raised [?]
4753ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            }
4763ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza        } else {
4773ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            pendingRelease->currentTexture = mCurrentTexture;
4783ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            pendingRelease->graphicBuffer =
4793ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza                    mCurrentTextureImage->graphicBuffer();
4803ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            pendingRelease->display = mEglDisplay;
4813ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
4823ce460440b0ab0b6d6407c9d8735b19f6e3b8408Dan Stoza            pendingRelease->isPending = true;
4832c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian        }
484bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
4852c8207e9627fe6c7a90e31fae8d71ae49df56845Mathias Agopian
4862adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // Update the GLConsumer state.
48747650f4f66a49e1815ad08ca4fb12a661d133abcPablo Ceballos    mCurrentTexture = slot;
488ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584Pablo Ceballos    mCurrentTextureImage = nextTextureImage;
489bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentCrop = item.mCrop;
490bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTransform = item.mTransform;
491bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentScalingMode = item.mScalingMode;
492bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentTimestamp = item.mTimestamp;
493bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter    mCurrentDataSpace = item.mDataSpace;
494bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mCurrentFence = item.mFence;
4953d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Anderson    mCurrentFenceTime = item.mFenceTime;
496d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    mCurrentFrameNumber = item.mFrameNumber;
497bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
498bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    computeCurrentTransformMatrixLocked();
499bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
500bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return err;
501bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
502bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
5032adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::bindTextureImageLocked() {
504bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    if (mEglDisplay == EGL_NO_DISPLAY) {
505bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        ALOGE("bindTextureImage: invalid display");
506bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
507bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
508bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
509d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLenum error;
510bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    while ((error = glGetError()) != GL_NO_ERROR) {
511d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
512bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
513bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
514bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    glBindTexture(mTexTarget, mTexName);
5155c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
5165c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            mCurrentTextureImage == NULL) {
517d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("bindTextureImage: no currently-bound texture");
5185c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return NO_INIT;
5195c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
5200eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
5215c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
5222d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                                                        mCurrentCrop);
5235c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (err != NO_ERROR) {
524d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
5255c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mEglDisplay, mCurrentTexture);
5265c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return UNKNOWN_ERROR;
5275c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
5285c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mCurrentTextureImage->bindToTextureTarget(mTexTarget);
5295c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
5302d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // In the rare case that the display is terminated and then initialized
5312d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // again, we can't detect that the display changed (it didn't), but the
5322d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // image is invalid. In this case, repeat the exact same steps while
5332d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    // forcing the creation of a new image.
5342d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    if ((error = glGetError()) != GL_NO_ERROR) {
5352d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        glBindTexture(mTexTarget, mTexName);
536d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay,
537d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                                                               mCurrentCrop,
538d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                                                               true);
539d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        if (result != NO_ERROR) {
540d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
5412d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                    mEglDisplay, mCurrentTexture);
5422d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner            return UNKNOWN_ERROR;
5432d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        }
5442d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
5452d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        if ((error = glGetError()) != GL_NO_ERROR) {
546d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
5472d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner            return UNKNOWN_ERROR;
5482d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner        }
549bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
55097eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden
55197eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    // Wait for the new buffer to be ready.
55297eba8904c2f221c42a9473407223a4c3a213f75Andy McFadden    return doGLFenceWaitLocked();
553bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
5549a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
55545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopianstatus_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
556bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLDisplay dpy = eglGetCurrentDisplay();
557bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    EGLContext ctx = eglGetCurrentContext();
55886edf4f6470ee0f108bf40d3c1d23bf0a78c9c38Jamie Gennis
55945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (!contextCheck) {
56045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // if this is the first time we're called, mEglDisplay/mEglContext have
56145155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        // never been set, so don't error out (below).
56245155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        if (mEglDisplay == EGL_NO_DISPLAY) {
56345155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            mEglDisplay = dpy;
56445155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
56546a1f6b40e1f7677cd41cd30f729ff66c7c21517Jesse Hall        if (mEglContext == EGL_NO_CONTEXT) {
56645155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian            mEglContext = ctx;
56745155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian        }
56845155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    }
56945155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian
57045155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
571d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
572bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
573bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
574b3e518c820c7dbe35587bd45c510e4e5e7cfd9c9Mathias Agopian
57545155969dc747d09d267cd1f22baf0eaf886a801Mathias Agopian    if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
576d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
577bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden        return INVALID_OPERATION;
5788ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
57950c4efc2a44fd312febeda76c8d1a6dc42cee8f8Jamie Gennis
580bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglDisplay = dpy;
581bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    mEglContext = ctx;
582bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    return NO_ERROR;
5838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
5848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
58513f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hallvoid GLConsumer::setReleaseFence(const sp<Fence>& fence) {
58613f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall    if (fence->isValid() &&
58713f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
588c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar        status_t err = addReleaseFence(mCurrentTexture,
5895c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                mCurrentTextureImage->graphicBuffer(), fence);
59013f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        if (err != OK) {
591d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
59213f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall                    strerror(-err), err);
59313f01cbdbd34779a234bc674df79e23672fd5c0bJesse Hall        }
594ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall    }
595ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall}
596ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
5972adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::detachFromContext() {
59874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
599d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("detachFromContext");
60074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
60174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
60274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
603d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: abandoned GLConsumer");
60474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
60574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
60674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
60774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (!mAttached) {
608d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
60974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
61074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
61174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
61274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
61374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
61474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
61574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
61674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
617d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: invalid current EGLDisplay");
61874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
61974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
62074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
622d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("detachFromContext: invalid current EGLContext");
62374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
62474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
62574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
62674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
62774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        status_t err = syncForReleaseLocked(dpy);
62874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        if (err != OK) {
62974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            return err;
63074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
63174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
63274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        glDeleteTextures(1, &mTexName);
63374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
63474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
63574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = EGL_NO_DISPLAY;
63674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = EGL_NO_CONTEXT;
63774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = false;
63874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
63974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
64074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
64174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
6423f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianstatus_t GLConsumer::attachToContext(uint32_t tex) {
64374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    ATRACE_CALL();
644d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("attachToContext");
64574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    Mutex::Autolock lock(mMutex);
64674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
64774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAbandoned) {
648d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: abandoned GLConsumer");
64974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return NO_INIT;
65074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
65174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
65274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (mAttached) {
653d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: GLConsumer is already attached to a "
65474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                "context");
65574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
65674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
65774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
65874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
65974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
66074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
66174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (dpy == EGL_NO_DISPLAY) {
662d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: invalid current EGLDisplay");
66374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
66474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
66574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
66674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    if (ctx == EGL_NO_CONTEXT) {
667d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("attachToContext: invalid current EGLContext");
66874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        return INVALID_OPERATION;
66974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
67074bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
67174bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // We need to bind the texture regardless of whether there's a current
67274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    // buffer.
6733f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    glBindTexture(mTexTarget, GLuint(tex));
67474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
67574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglDisplay = dpy;
67674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mEglContext = ctx;
67774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mTexName = tex;
67874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    mAttached = true;
67974bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
6805c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mCurrentTextureImage != NULL) {
6815c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // This may wait for a buffer a second time. This is likely required if
6825c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // this is a different context, since otherwise the wait could be skipped
6835c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // by bouncing through another context. For the same context the extra
6845c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // wait is redundant.
6855c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        status_t err =  bindTextureImageLocked();
6865c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (err != NO_ERROR) {
6875c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            return err;
6885c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
689bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden    }
690bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
6915c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return OK;
692bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden}
693bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
694bf974abe92f7495529916fe0f483f3b56e7c30e3Andy McFadden
6952adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
696d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("syncForReleaseLocked");
69774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
69801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
699ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useNativeFenceSync()) {
70001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
70101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
70201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
703d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
70401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
70574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis                return UNKNOWN_ERROR;
70674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis            }
70701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
70801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
70998ff0597bd9e57ba133d54f8f09841f96955cba1Jamie Gennis            eglDestroySyncKHR(dpy, sync);
71001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
711d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
71201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "fd: %#x", eglGetError());
71301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
71401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
71501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            sp<Fence> fence(new Fence(fenceFd));
716c5d7b7d323bba8772a9005f7d300ad983a04733aLajos Molnar            status_t err = addReleaseFenceLocked(mCurrentTexture,
7175c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner                    mCurrentTextureImage->graphicBuffer(), fence);
71801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (err != OK) {
719d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error adding release fence: "
72001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        "%s (%d)", strerror(-err), err);
72101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return err;
72201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
723ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
72401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
72501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence != EGL_NO_SYNC_KHR) {
72601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // There is already a fence for the current slot.  We need to
72701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // wait on that before replacing it with another fence to
72801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // ensure that all outstanding buffer accesses have completed
72901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                // before the producer accesses it.
73001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
73101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                if (result == EGL_FALSE) {
732d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                    GLC_LOGE("syncForReleaseLocked: error waiting for previous "
73301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence: %#x", eglGetError());
73401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return UNKNOWN_ERROR;
73501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
736d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                    GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
73701dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                            "fence");
73801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                    return TIMED_OUT;
73901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                }
74001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                eglDestroySyncKHR(dpy, fence);
74101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
74274bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
74301dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // Create a fence for the outstanding accesses in the current
74401dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            // OpenGL ES context.
74501dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
74601dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            if (fence == EGL_NO_SYNC_KHR) {
747d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
74801dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                        eglGetError());
74901dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis                return UNKNOWN_ERROR;
75001dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            }
75101dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            glFlush();
75201dbf5539bff4bece3f9bbfa55046b04a8a45e99Jamie Gennis            mEglSlots[mCurrentTexture].mEglFence = fence;
75374bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis        }
75474bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    }
75574bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
75674bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis    return OK;
75774bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis}
75874bed55fff0132be319bcd1703970516ae28b3a9Jamie Gennis
759d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stozabool GLConsumer::isExternalFormat(PixelFormat format)
7607a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
7617a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
7627a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
7637a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
7647a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
7657a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
7667a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
7677a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
7687a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7697a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
7707a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7717a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
7727a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
7737a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
7747a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7757a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
7767a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7777a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7783f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianuint32_t GLConsumer::getCurrentTextureTarget() const {
779fb1b5a2f333800574b0da435d1200cf9b13d723fJamie Gennis    return mTexTarget;
7807a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
7817a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
7822adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::getTransformMatrix(float mtx[16]) {
783f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
784736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
785736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis}
786736aa9573bb7b78f9c315f396c104491b3639426Jamie Gennis
7872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setFilteringEnabled(bool enabled) {
7885c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    Mutex::Autolock lock(mMutex);
789e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    if (mAbandoned) {
790d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
791e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        return;
792e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
7935c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    bool needsRecompute = mFilteringEnabled != enabled;
7945c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    mFilteringEnabled = enabled;
795e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
7965c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (needsRecompute && mCurrentTextureImage==NULL) {
797d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
798e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian    }
799e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian
8005c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (needsRecompute && mCurrentTextureImage != NULL) {
801e96e9e1093b5700e9f403a6e2479da7dc36d3b71Mathias Agopian        computeCurrentTransformMatrixLocked();
8025c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis    }
8035c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis}
8045c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
8052adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::computeCurrentTransformMatrixLocked() {
806d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("computeCurrentTransformMatrixLocked");
8071a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
8081a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            nullptr : mCurrentTextureImage->graphicBuffer();
8091a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    if (buf == nullptr) {
8101a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        GLC_LOGD("computeCurrentTransformMatrixLocked: "
8111a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                "mCurrentTextureImage is NULL");
8121a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    }
8131a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    computeTransformMatrix(mCurrentTransformMatrix, buf,
8141a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
8151a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        mCurrentTransform, mFilteringEnabled);
8161a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck}
8171a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck
8181a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reckvoid GLConsumer::computeTransformMatrix(float outTransform[16],
8191a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
8201a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        bool filtering) {
821f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
822a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
823a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
824a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
825a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
8261a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
827a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
828a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
829a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
830a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
831a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
832a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
8331a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
834a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
835a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
836a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
837a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
838a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
839a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
8401a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
841a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
842a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
843a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
844a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
845a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
846f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
847f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
848dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    float mtxBeforeFlipV[16];
8491a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    if (!cropRect.isEmpty()) {
850dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
851dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float bufferWidth = buf->getWidth();
852dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float bufferHeight = buf->getHeight();
8531a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        float shrinkAmount = 0.0f;
8541a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        if (filtering) {
8551a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            // In order to prevent bilinear sampling beyond the edge of the
8561a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            // crop rectangle we may need to shrink it by 2 texels in each
8571a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            // dimension.  Normally this would just need to take 1/2 a texel
8581a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            // off each end, but because the chroma channels of YUV420 images
8591a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            // are subsampled we may need to shrink the crop region by a whole
8601a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            // texel on each side.
8611a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            switch (buf->getPixelFormat()) {
8621a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                case PIXEL_FORMAT_RGBA_8888:
8631a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                case PIXEL_FORMAT_RGBX_8888:
864ff415149dc5a83a4eb5960daf2cb2c310ef89847Romain Guy                case PIXEL_FORMAT_RGBA_FP16:
865541f22658ab1617c9d12c98684ab40248df8749bRomain Guy                case PIXEL_FORMAT_RGBA_1010102:
8661a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                case PIXEL_FORMAT_RGB_888:
8671a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                case PIXEL_FORMAT_RGB_565:
8681a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                case PIXEL_FORMAT_BGRA_8888:
8691a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    // We know there's no subsampling of any channels, so we
8701a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    // only need to shrink by a half a pixel.
8711a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    shrinkAmount = 0.5;
8721a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    break;
8731a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck
8741a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                default:
8751a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    // If we don't recognize the format, we must assume the
8761a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    // worst case (that we care about), which is YUV420.
8771a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    shrinkAmount = 1.0;
8781a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    break;
8795c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis            }
8801a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        }
8815c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis
8821a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        // Only shrink the dimensions that are not the size of the buffer.
8831a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        if (cropRect.width() < bufferWidth) {
8841a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
8851a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
8861a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    bufferWidth;
8871a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        }
8881a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck        if (cropRect.height() < bufferHeight) {
8891a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
8901a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    bufferHeight;
8911a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
8921a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck                    bufferHeight;
8935c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
894dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        float crop[16] = {
895dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            sx, 0, 0, 0,
896dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            0, sy, 0, 0,
897dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            0, 0, 1, 0,
898dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            tx, ty, 0, 1,
899dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        };
900dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis
901dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        mtxMul(mtxBeforeFlipV, crop, xform);
902dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis    } else {
903dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis        for (int i = 0; i < 16; i++) {
904dbe9245e2e362b12e184cd33b9a27b0901f81244Jamie Gennis            mtxBeforeFlipV[i] = xform[i];
9055c1139fea3cc0fd9847a6594d853a458152b2fbcJamie Gennis        }
906a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
907a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
908a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
9092adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden    // coordinate of 0, so GLConsumer must behave the same way.  We don't
910a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
911a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
9121a61da5e28fa16ad556a58193c8bbeb32a5f636dJohn Reck    mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
913f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
914f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
9152adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddennsecs_t GLConsumer::getTimestamp() {
916d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("getTimestamp");
9171d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
9181d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
9191d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
9201d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
921bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchterandroid_dataspace GLConsumer::getCurrentDataSpace() {
922bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter    GLC_LOGV("getCurrentDataSpace");
923bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter    Mutex::Autolock lock(mMutex);
924bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter    return mCurrentDataSpace;
925bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter}
926bb09b436fa119ad8b97f1bf5c04cc5aa10b5f1f0Courtney Goeltzenleuchter
927d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stozauint64_t GLConsumer::getFrameNumber() {
928d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("getFrameNumber");
929d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    Mutex::Autolock lock(mMutex);
930d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala    return mCurrentFrameNumber;
931d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala}
932d171da973de3c6b30263011334fdcd916739144fEino-Ville Talvala
93306d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wusp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
9347a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
93506d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wu
93606d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wu    if (outSlot != nullptr) {
93706d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wu        *outSlot = mCurrentTexture;
93806d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wu    }
93906d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wu
94006d63de03cb2a551ca99608f5aa0c4f3e200b0fcChia-I Wu    return (mCurrentTextureImage == nullptr) ?
9415c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            NULL : mCurrentTextureImage->graphicBuffer();
9427a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9437a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9442adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenRect GLConsumer::getCurrentCrop() const {
9457a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
946016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
947016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    Rect outCrop = mCurrentCrop;
948016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
949d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
950d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
951016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
952016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
953016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
954d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGV("too wide: newWidth = %d", newWidth);
955016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
956016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
957d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            GLC_LOGV("too tall: newHeight = %d", newHeight);
958016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
959016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
960d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
961d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
962d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza
963016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too wide
964d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        if (newWidth < currentWidth) {
965ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            uint32_t dw = currentWidth - newWidth;
966ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            auto halfdw = dw / 2;
967ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            outCrop.left += halfdw;
968ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            // Not halfdw because it would subtract 1 too few when dw is odd
969ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            outCrop.right -= (dw - halfdw);
970016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        // The crop is too tall
971d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        } else if (newHeight < currentHeight) {
972ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            uint32_t dh = currentHeight - newHeight;
973ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            auto halfdh = dh / 2;
974ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            outCrop.top += halfdh;
975ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            // Not halfdh because it would subtract 1 too few when dh is odd
976ec4cb387502d5bd09e49b55605cf679fe3a0207aDan Stoza            outCrop.bottom -= (dh - halfdh);
977016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam        }
978016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
979d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
980016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.left, outCrop.top,
981016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam            outCrop.right,outCrop.bottom);
982016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    }
983016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam
984016c8cbce4dde21f2703b9865f52d16b8d5d5ae2Daniel Lam    return outCrop;
9857a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9867a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentTransform() const {
9887a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
9897a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
9907a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
9917a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
9922adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenuint32_t GLConsumer::getCurrentScalingMode() const {
9937734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    Mutex::Autolock lock(mMutex);
9947734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian    return mCurrentScalingMode;
9957734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian}
9967734ebfe47f42f980c1b44c1f284a91d8ad1d6c7Mathias Agopian
9972adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddensp<Fence> GLConsumer::getCurrentFence() const {
998dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    Mutex::Autolock lock(mMutex);
999dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall    return mCurrentFence;
1000dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall}
1001dc5b485f74edf2d2f31c62054eb6c180421a3adeJesse Hall
10023d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Andersonstd::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
10033d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Anderson    Mutex::Autolock lock(mMutex);
10043d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Anderson    return mCurrentFenceTime;
10053d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Anderson}
10063d4039d7a291cd9b6f2dd4b46fcdb576f2db3356Brian Anderson
10072adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWait() const {
100861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    Mutex::Autolock lock(mMutex);
10093941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis    return doGLFenceWaitLocked();
10103941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis}
10113941cb240d438bfdebe24920bb2ada86456a0bf9Jamie Gennis
10122adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::doGLFenceWaitLocked() const {
101361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
101461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLDisplay dpy = eglGetCurrentDisplay();
101561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    EGLContext ctx = eglGetCurrentContext();
101661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
101761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
1018d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
101961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
102061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
102161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
102261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
1023d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza        GLC_LOGE("doGLFenceWait: invalid current EGLContext");
102461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        return INVALID_OPERATION;
102561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
102661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
10271df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (mCurrentFence->isValid()) {
1028ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian        if (SyncFeatures::getInstance().useWaitSync()) {
102961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // Create an EGLSyncKHR from the current fence.
103061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            int fenceFd = mCurrentFence->dup();
103161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (fenceFd == -1) {
1032d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
103361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return -errno;
103461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
103561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint attribs[] = {
103661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
103761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                EGL_NONE
103861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            };
103961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
104061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
104161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (sync == EGL_NO_SYNC_KHR) {
104261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                close(fenceFd);
1043d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
104461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglGetError());
104561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
104661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
104761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
104861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // XXX: The spec draft is inconsistent as to whether this should
104961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // return an EGLint or void.  Ignore the return value for now, as
105061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            // it's not strictly needed.
10512bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian            eglWaitSyncKHR(dpy, sync, 0);
105261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            EGLint eglErr = eglGetError();
105361e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            eglDestroySyncKHR(dpy, sync);
105461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (eglErr != EGL_SUCCESS) {
1055d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
105661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                        eglErr);
105761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return UNKNOWN_ERROR;
105861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
105961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        } else {
1060ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopian            status_t err = mCurrentFence->waitForever(
10612adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden                    "GLConsumer::doGLFenceWaitLocked");
106261e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            if (err != NO_ERROR) {
1063d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
106461e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis                return err;
106561e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis            }
106661e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis        }
106761e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    }
106861e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
106961e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis    return NO_ERROR;
107061e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis}
107161e04b92bdeafc6fca89052d14dab1bd0c384a71Jamie Gennis
10722adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::freeBufferLocked(int slotIndex) {
1073d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
10749abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    if (slotIndex == mCurrentTexture) {
10759abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
10769abe1ebc9575dc5a19bf1dfce6e9b02e03374457Daniel Lam    }
10775c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mEglSlots[slotIndex].mEglImage.clear();
10789fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::freeBufferLocked(slotIndex);
1079fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis}
1080fa5b40ebb8923133df12dc70591bfe35b3f1c9b3Jamie Gennis
10812adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::abandonLocked() {
1082d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    GLC_LOGV("abandonLocked");
10835c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mCurrentTextureImage.clear();
10849fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis    ConsumerBase::abandonLocked();
10857b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis}
10867b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis
10872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenvoid GLConsumer::setName(const String8& name) {
1088eae59d2ea77ef57aab203fb185a880ce37ac38d6Daniel Lam    Mutex::Autolock _l(mMutex);
108965d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
109065d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setName: GLConsumer is abandoned!");
109165d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return;
109265d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
1093fa28c35c21d1bf8b38f541758c291bc17a2d7270Jamie Gennis    mName = name;
1094db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    mConsumer->setConsumerName(name);
1095b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1096b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
1097d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stozastatus_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
1098b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
109965d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
110065d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
110165d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return NO_INIT;
110265d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
1103db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setDefaultBufferFormat(defaultFormat);
1104b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1105b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
11065b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvalastatus_t GLConsumer::setDefaultBufferDataSpace(
11075b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala        android_dataspace defaultDataSpace) {
11085b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
110965d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
111065d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
111165d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return NO_INIT;
111265d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
11135b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala    return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
11145b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala}
11155b75a513e431c097ae704cba2f7affa6bfaecec9Eino-Ville Talvala
11162adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
1117b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
111865d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
111965d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
112065d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return NO_INIT;
112165d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
112285b217668d6840c8e6a109adfb99461313676f8dEino-Ville Talvala    usage |= DEFAULT_USAGE_FLAGS;
1123db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setConsumerUsageBits(usage);
1124b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1125b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
11262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenstatus_t GLConsumer::setTransformHint(uint32_t hint) {
1127b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam    Mutex::Autolock lock(mMutex);
112865d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
112965d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
113065d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return NO_INIT;
113165d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
1132db89edc94bd2a78226b407f9f7261e202e7fa325Mathias Agopian    return mConsumer->setTransformHint(hint);
1133b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam}
1134b267579ba8dfe3f47d2a481c5a3c2254e3d565a1Daniel Lam
113519e3e06e3c65a7c001a6fe0971744ba5ff536515Pablo Ceballosstatus_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
113619e3e06e3c65a7c001a6fe0971744ba5ff536515Pablo Ceballos    Mutex::Autolock lock(mMutex);
113765d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    if (mAbandoned) {
113865d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
113965d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos        return NO_INIT;
114065d9f6d63ab3bad1d835df14c662028a748eb3c5Pablo Ceballos    }
114119e3e06e3c65a7c001a6fe0971744ba5ff536515Pablo Ceballos    return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
114219e3e06e3c65a7c001a6fe0971744ba5ff536515Pablo Ceballos}
114319e3e06e3c65a7c001a6fe0971744ba5ff536515Pablo Ceballos
114474d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopianvoid GLConsumer::dumpLocked(String8& result, const char* prefix) const
114568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian{
114674d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    result.appendFormat(
11479fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smTexName=%d mCurrentTexture=%d\n"
11489fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
11499fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
11509fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
11519fea3421ffddf6480f57f55a25936a886043d909Jamie Gennis       mCurrentTransform);
115268c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
115374d211ae26a0257c6075a823812e40b55aa1e653Mathias Agopian    ConsumerBase::dumpLocked(result, prefix);
115468c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian}
115568c7794183a7dbfe3b20d4ce832f8eb79c2c619aMathias Agopian
1156f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
1157f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1158f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1159f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1160f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1161f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1162f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1163f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1164f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1165f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1166f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1167f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1168f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1169f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1170f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1171f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
1172f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1173f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1174f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1175f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1176f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
1177f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
11785c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric PennerGLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
11795c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mGraphicBuffer(graphicBuffer),
11805c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    mEglImage(EGL_NO_IMAGE_KHR),
118160d6922a011fe18c111b8d30fb6ef1f655b6b15ePablo Ceballos    mEglDisplay(EGL_NO_DISPLAY),
118260d6922a011fe18c111b8d30fb6ef1f655b6b15ePablo Ceballos    mCropRect(Rect::EMPTY_RECT) {
11835c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
11845c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11855c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric PennerGLConsumer::EglImage::~EglImage() {
11865c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mEglImage != EGL_NO_IMAGE_KHR) {
11875c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
11885c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner           ALOGE("~EglImage: eglDestroyImageKHR failed");
11895c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
119078be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine        eglTerminate(mEglDisplay);
11915c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
11925c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
11935c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
11945c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Pennerstatus_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
11952d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                                              const Rect& cropRect,
11962d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner                                              bool forceCreation) {
11975c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // If there's an image and it's no longer valid, destroy it.
11985c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
11995c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    bool displayInvalid = mEglDisplay != eglDisplay;
12005c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
12012d14a0ed4f5861bfa67e9db138ffdc70d2d5e6e4Eric Penner    if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
12025c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
12035c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner           ALOGE("createIfNeeded: eglDestroyImageKHR failed");
12045c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        }
120578be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine        eglTerminate(mEglDisplay);
12065c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglImage = EGL_NO_IMAGE_KHR;
12075c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglDisplay = EGL_NO_DISPLAY;
12085c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
12095c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
12105c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // If there's no image, create one.
12115c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mEglImage == EGL_NO_IMAGE_KHR) {
12125c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglDisplay = eglDisplay;
12135c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mCropRect = cropRect;
12145c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
12155c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
12165c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
12175c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    // Fail if we can't create a valid image.
12185c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (mEglImage == EGL_NO_IMAGE_KHR) {
12195c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mEglDisplay = EGL_NO_DISPLAY;
12205c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        mCropRect.makeInvalid();
12215c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        const sp<GraphicBuffer>& buffer = mGraphicBuffer;
12225c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
12235c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
12245c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            buffer->getUsage(), buffer->getPixelFormat());
12255c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        return UNKNOWN_ERROR;
12265c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
12275c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
12285c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return OK;
12295c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
12305c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
12315c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Pennervoid GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1232d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    glEGLImageTargetTexture2DOES(texTarget,
1233d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            static_cast<GLeglImageOES>(mEglImage));
12345c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
12355c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
12365c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric PennerEGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
12375c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
1238d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    EGLClientBuffer cbuf =
1239d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza            static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1240aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner    const bool createProtectedImage =
1241aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner            (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
1242aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner            hasEglProtectedContent();
12435c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    EGLint attrs[] = {
12445c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
12455c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
12465c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
12475c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
12485c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
1249aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner        createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1250aec8697fcaa8bb30e335f7850cffdd0364c35532Craig Donner        createProtectedImage ? EGL_TRUE : EGL_NONE,
12515c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGL_NONE,
12525c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    };
12535c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (!crop.isValid()) {
1254a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        // No crop rect to set, so leave the crop out of the attrib array. Make
1255a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        // sure to propagate the protected content attrs if they are set.
1256a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        attrs[2] = attrs[10];
1257a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        attrs[3] = attrs[11];
1258a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        attrs[4] = EGL_NONE;
12595c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    } else if (!isEglImageCroppable(crop)) {
12605c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // The crop rect is not at the origin, so we can't set the crop on the
12615c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
12625c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // extension.  In the future we can add a layered extension that
12635c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        // removes this restriction if there is hardware that can support it.
1264a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        attrs[2] = attrs[10];
1265a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        attrs[3] = attrs[11];
1266a94d940c75456714b1c4425dde1e44802cb838f7Craig Donner        attrs[4] = EGL_NONE;
12675c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
126878be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine    eglInitialize(dpy, 0, 0);
12695c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
12705c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
12715c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    if (image == EGL_NO_IMAGE_KHR) {
12725c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        EGLint error = eglGetError();
12735c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner        ALOGE("error creating EGLImage: %#x", error);
127478be65e7bf6898c6afa55c9016f331ab1aa2503aMichael Lentine        eglTerminate(dpy);
12755c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    }
12765c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner    return image;
12775c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner}
12785c3d243fcca6d0678bcbb0461bbbe0b63f35212cEric Penner
12798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
1280