xref: /aosp_15_r20/frameworks/native/libs/gui/GLConsumer.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "GLConsumer"
18*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19*38e8c45fSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
20*38e8c45fSAndroid Build Coastguard Worker 
21*38e8c45fSAndroid Build Coastguard Worker #define GL_GLEXT_PROTOTYPES
22*38e8c45fSAndroid Build Coastguard Worker #define EGL_EGLEXT_PROTOTYPES
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker #include <EGL/egl.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <EGL/eglext.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <GLES2/gl2.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <GLES2/gl2ext.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <cutils/compiler.h>
31*38e8c45fSAndroid Build Coastguard Worker 
32*38e8c45fSAndroid Build Coastguard Worker #include <hardware/hardware.h>
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker #include <math/mat4.h>
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker #include <gui/BufferItem.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <gui/DebugEGLImageTracker.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <gui/GLConsumer.h>
39*38e8c45fSAndroid Build Coastguard Worker #include <gui/ISurfaceComposer.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceComposerClient.h>
41*38e8c45fSAndroid Build Coastguard Worker 
42*38e8c45fSAndroid Build Coastguard Worker #include <private/gui/ComposerService.h>
43*38e8c45fSAndroid Build Coastguard Worker #include <private/gui/SyncFeatures.h>
44*38e8c45fSAndroid Build Coastguard Worker 
45*38e8c45fSAndroid Build Coastguard Worker #include <utils/Log.h>
46*38e8c45fSAndroid Build Coastguard Worker #include <utils/String8.h>
47*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
48*38e8c45fSAndroid Build Coastguard Worker 
49*38e8c45fSAndroid Build Coastguard Worker #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
50*38e8c45fSAndroid Build Coastguard Worker #define EGL_PROTECTED_CONTENT_EXT 0x32C0
51*38e8c45fSAndroid Build Coastguard Worker 
52*38e8c45fSAndroid Build Coastguard Worker namespace android {
53*38e8c45fSAndroid Build Coastguard Worker 
54*38e8c45fSAndroid Build Coastguard Worker // Macros for including the GLConsumer name in log messages
55*38e8c45fSAndroid Build Coastguard Worker #define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
56*38e8c45fSAndroid Build Coastguard Worker #define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
57*38e8c45fSAndroid Build Coastguard Worker // #define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.c_str(), ##__VA_ARGS__)
58*38e8c45fSAndroid Build Coastguard Worker #define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
59*38e8c45fSAndroid Build Coastguard Worker #define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)
60*38e8c45fSAndroid Build Coastguard Worker 
61*38e8c45fSAndroid Build Coastguard Worker static const struct {
62*38e8c45fSAndroid Build Coastguard Worker     uint32_t width, height;
63*38e8c45fSAndroid Build Coastguard Worker     char const* bits;
64*38e8c45fSAndroid Build Coastguard Worker } kDebugData = { 15, 12,
65*38e8c45fSAndroid Build Coastguard Worker     "_______________"
66*38e8c45fSAndroid Build Coastguard Worker     "_______________"
67*38e8c45fSAndroid Build Coastguard Worker     "_____XX_XX_____"
68*38e8c45fSAndroid Build Coastguard Worker     "__X_X_____X_X__"
69*38e8c45fSAndroid Build Coastguard Worker     "__X_XXXXXXX_X__"
70*38e8c45fSAndroid Build Coastguard Worker     "__XXXXXXXXXXX__"
71*38e8c45fSAndroid Build Coastguard Worker     "___XX_XXX_XX___"
72*38e8c45fSAndroid Build Coastguard Worker     "____XXXXXXX____"
73*38e8c45fSAndroid Build Coastguard Worker     "_____X___X_____"
74*38e8c45fSAndroid Build Coastguard Worker     "____X_____X____"
75*38e8c45fSAndroid Build Coastguard Worker     "_______________"
76*38e8c45fSAndroid Build Coastguard Worker     "_______________"
77*38e8c45fSAndroid Build Coastguard Worker };
78*38e8c45fSAndroid Build Coastguard Worker 
79*38e8c45fSAndroid Build Coastguard Worker static const mat4 mtxIdentity;
80*38e8c45fSAndroid Build Coastguard Worker 
81*38e8c45fSAndroid Build Coastguard Worker Mutex GLConsumer::sStaticInitLock;
82*38e8c45fSAndroid Build Coastguard Worker sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
83*38e8c45fSAndroid Build Coastguard Worker 
hasEglProtectedContentImpl()84*38e8c45fSAndroid Build Coastguard Worker static bool hasEglProtectedContentImpl() {
85*38e8c45fSAndroid Build Coastguard Worker     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
86*38e8c45fSAndroid Build Coastguard Worker     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
87*38e8c45fSAndroid Build Coastguard Worker     size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
88*38e8c45fSAndroid Build Coastguard Worker     size_t extsLen = strlen(exts);
89*38e8c45fSAndroid Build Coastguard Worker     bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
90*38e8c45fSAndroid Build Coastguard Worker     bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
91*38e8c45fSAndroid Build Coastguard Worker     bool atEnd = (cropExtLen+1) < extsLen &&
92*38e8c45fSAndroid Build Coastguard Worker             !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
93*38e8c45fSAndroid Build Coastguard Worker     bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
94*38e8c45fSAndroid Build Coastguard Worker     return equal || atStart || atEnd || inMiddle;
95*38e8c45fSAndroid Build Coastguard Worker }
96*38e8c45fSAndroid Build Coastguard Worker 
hasEglProtectedContent()97*38e8c45fSAndroid Build Coastguard Worker static bool hasEglProtectedContent() {
98*38e8c45fSAndroid Build Coastguard Worker     // Only compute whether the extension is present once the first time this
99*38e8c45fSAndroid Build Coastguard Worker     // function is called.
100*38e8c45fSAndroid Build Coastguard Worker     static bool hasIt = hasEglProtectedContentImpl();
101*38e8c45fSAndroid Build Coastguard Worker     return hasIt;
102*38e8c45fSAndroid Build Coastguard Worker }
103*38e8c45fSAndroid Build Coastguard Worker 
104*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
GLConsumer(uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)105*38e8c45fSAndroid Build Coastguard Worker GLConsumer::GLConsumer(uint32_t tex, uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
106*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(isControlledByApp, /* isConsumerSurfaceFlinger */ false),
107*38e8c45fSAndroid Build Coastguard Worker         mCurrentCrop(Rect::EMPTY_RECT),
108*38e8c45fSAndroid Build Coastguard Worker         mCurrentTransform(0),
109*38e8c45fSAndroid Build Coastguard Worker         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
110*38e8c45fSAndroid Build Coastguard Worker         mCurrentFence(Fence::NO_FENCE),
111*38e8c45fSAndroid Build Coastguard Worker         mCurrentTimestamp(0),
112*38e8c45fSAndroid Build Coastguard Worker         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
113*38e8c45fSAndroid Build Coastguard Worker         mCurrentFrameNumber(0),
114*38e8c45fSAndroid Build Coastguard Worker         mDefaultWidth(1),
115*38e8c45fSAndroid Build Coastguard Worker         mDefaultHeight(1),
116*38e8c45fSAndroid Build Coastguard Worker         mFilteringEnabled(true),
117*38e8c45fSAndroid Build Coastguard Worker         mTexName(tex),
118*38e8c45fSAndroid Build Coastguard Worker         mUseFenceSync(useFenceSync),
119*38e8c45fSAndroid Build Coastguard Worker         mTexTarget(texTarget),
120*38e8c45fSAndroid Build Coastguard Worker         mEglDisplay(EGL_NO_DISPLAY),
121*38e8c45fSAndroid Build Coastguard Worker         mEglContext(EGL_NO_CONTEXT),
122*38e8c45fSAndroid Build Coastguard Worker         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
123*38e8c45fSAndroid Build Coastguard Worker         mAttached(true) {
124*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("GLConsumer");
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker     memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
129*38e8c45fSAndroid Build Coastguard Worker }
130*38e8c45fSAndroid Build Coastguard Worker #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
131*38e8c45fSAndroid Build Coastguard Worker 
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)132*38e8c45fSAndroid Build Coastguard Worker GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
133*38e8c45fSAndroid Build Coastguard Worker         uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
134*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase(bq, isControlledByApp),
135*38e8c45fSAndroid Build Coastguard Worker     mCurrentCrop(Rect::EMPTY_RECT),
136*38e8c45fSAndroid Build Coastguard Worker     mCurrentTransform(0),
137*38e8c45fSAndroid Build Coastguard Worker     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
138*38e8c45fSAndroid Build Coastguard Worker     mCurrentFence(Fence::NO_FENCE),
139*38e8c45fSAndroid Build Coastguard Worker     mCurrentTimestamp(0),
140*38e8c45fSAndroid Build Coastguard Worker     mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
141*38e8c45fSAndroid Build Coastguard Worker     mCurrentFrameNumber(0),
142*38e8c45fSAndroid Build Coastguard Worker     mDefaultWidth(1),
143*38e8c45fSAndroid Build Coastguard Worker     mDefaultHeight(1),
144*38e8c45fSAndroid Build Coastguard Worker     mFilteringEnabled(true),
145*38e8c45fSAndroid Build Coastguard Worker     mTexName(tex),
146*38e8c45fSAndroid Build Coastguard Worker     mUseFenceSync(useFenceSync),
147*38e8c45fSAndroid Build Coastguard Worker     mTexTarget(texTarget),
148*38e8c45fSAndroid Build Coastguard Worker     mEglDisplay(EGL_NO_DISPLAY),
149*38e8c45fSAndroid Build Coastguard Worker     mEglContext(EGL_NO_CONTEXT),
150*38e8c45fSAndroid Build Coastguard Worker     mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
151*38e8c45fSAndroid Build Coastguard Worker     mAttached(true)
152*38e8c45fSAndroid Build Coastguard Worker {
153*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("GLConsumer");
154*38e8c45fSAndroid Build Coastguard Worker 
155*38e8c45fSAndroid Build Coastguard Worker     memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
156*38e8c45fSAndroid Build Coastguard Worker             sizeof(mCurrentTransformMatrix));
157*38e8c45fSAndroid Build Coastguard Worker 
158*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
159*38e8c45fSAndroid Build Coastguard Worker }
160*38e8c45fSAndroid Build Coastguard Worker 
161*38e8c45fSAndroid Build Coastguard Worker #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
GLConsumer(uint32_t texTarget,bool useFenceSync,bool isControlledByApp)162*38e8c45fSAndroid Build Coastguard Worker GLConsumer::GLConsumer(uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
163*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(isControlledByApp, /* isConsumerSurfaceFlinger */ false),
164*38e8c45fSAndroid Build Coastguard Worker         mCurrentCrop(Rect::EMPTY_RECT),
165*38e8c45fSAndroid Build Coastguard Worker         mCurrentTransform(0),
166*38e8c45fSAndroid Build Coastguard Worker         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
167*38e8c45fSAndroid Build Coastguard Worker         mCurrentFence(Fence::NO_FENCE),
168*38e8c45fSAndroid Build Coastguard Worker         mCurrentTimestamp(0),
169*38e8c45fSAndroid Build Coastguard Worker         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
170*38e8c45fSAndroid Build Coastguard Worker         mCurrentFrameNumber(0),
171*38e8c45fSAndroid Build Coastguard Worker         mDefaultWidth(1),
172*38e8c45fSAndroid Build Coastguard Worker         mDefaultHeight(1),
173*38e8c45fSAndroid Build Coastguard Worker         mFilteringEnabled(true),
174*38e8c45fSAndroid Build Coastguard Worker         mTexName(0),
175*38e8c45fSAndroid Build Coastguard Worker         mUseFenceSync(useFenceSync),
176*38e8c45fSAndroid Build Coastguard Worker         mTexTarget(texTarget),
177*38e8c45fSAndroid Build Coastguard Worker         mEglDisplay(EGL_NO_DISPLAY),
178*38e8c45fSAndroid Build Coastguard Worker         mEglContext(EGL_NO_CONTEXT),
179*38e8c45fSAndroid Build Coastguard Worker         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
180*38e8c45fSAndroid Build Coastguard Worker         mAttached(false) {
181*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("GLConsumer");
182*38e8c45fSAndroid Build Coastguard Worker 
183*38e8c45fSAndroid Build Coastguard Worker     memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
184*38e8c45fSAndroid Build Coastguard Worker 
185*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
186*38e8c45fSAndroid Build Coastguard Worker }
187*38e8c45fSAndroid Build Coastguard Worker #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
188*38e8c45fSAndroid Build Coastguard Worker 
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)189*38e8c45fSAndroid Build Coastguard Worker GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget, bool useFenceSync,
190*38e8c45fSAndroid Build Coastguard Worker                        bool isControlledByApp)
191*38e8c45fSAndroid Build Coastguard Worker       : ConsumerBase(bq, isControlledByApp),
192*38e8c45fSAndroid Build Coastguard Worker         mCurrentCrop(Rect::EMPTY_RECT),
193*38e8c45fSAndroid Build Coastguard Worker         mCurrentTransform(0),
194*38e8c45fSAndroid Build Coastguard Worker         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
195*38e8c45fSAndroid Build Coastguard Worker         mCurrentFence(Fence::NO_FENCE),
196*38e8c45fSAndroid Build Coastguard Worker         mCurrentTimestamp(0),
197*38e8c45fSAndroid Build Coastguard Worker         mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
198*38e8c45fSAndroid Build Coastguard Worker         mCurrentFrameNumber(0),
199*38e8c45fSAndroid Build Coastguard Worker         mDefaultWidth(1),
200*38e8c45fSAndroid Build Coastguard Worker         mDefaultHeight(1),
201*38e8c45fSAndroid Build Coastguard Worker         mFilteringEnabled(true),
202*38e8c45fSAndroid Build Coastguard Worker         mTexName(0),
203*38e8c45fSAndroid Build Coastguard Worker         mUseFenceSync(useFenceSync),
204*38e8c45fSAndroid Build Coastguard Worker         mTexTarget(texTarget),
205*38e8c45fSAndroid Build Coastguard Worker         mEglDisplay(EGL_NO_DISPLAY),
206*38e8c45fSAndroid Build Coastguard Worker         mEglContext(EGL_NO_CONTEXT),
207*38e8c45fSAndroid Build Coastguard Worker         mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
208*38e8c45fSAndroid Build Coastguard Worker         mAttached(false) {
209*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("GLConsumer");
210*38e8c45fSAndroid Build Coastguard Worker 
211*38e8c45fSAndroid Build Coastguard Worker     memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
212*38e8c45fSAndroid Build Coastguard Worker             sizeof(mCurrentTransformMatrix));
213*38e8c45fSAndroid Build Coastguard Worker 
214*38e8c45fSAndroid Build Coastguard Worker     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
215*38e8c45fSAndroid Build Coastguard Worker }
216*38e8c45fSAndroid Build Coastguard Worker 
setDefaultBufferSize(uint32_t w,uint32_t h)217*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
218*38e8c45fSAndroid Build Coastguard Worker {
219*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
220*38e8c45fSAndroid Build Coastguard Worker     if (mAbandoned) {
221*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
222*38e8c45fSAndroid Build Coastguard Worker         return NO_INIT;
223*38e8c45fSAndroid Build Coastguard Worker     }
224*38e8c45fSAndroid Build Coastguard Worker     mDefaultWidth = w;
225*38e8c45fSAndroid Build Coastguard Worker     mDefaultHeight = h;
226*38e8c45fSAndroid Build Coastguard Worker     return mConsumer->setDefaultBufferSize(w, h);
227*38e8c45fSAndroid Build Coastguard Worker }
228*38e8c45fSAndroid Build Coastguard Worker 
updateTexImage()229*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::updateTexImage() {
230*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
231*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("updateTexImage");
232*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
233*38e8c45fSAndroid Build Coastguard Worker 
234*38e8c45fSAndroid Build Coastguard Worker     if (mAbandoned) {
235*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
236*38e8c45fSAndroid Build Coastguard Worker         return NO_INIT;
237*38e8c45fSAndroid Build Coastguard Worker     }
238*38e8c45fSAndroid Build Coastguard Worker 
239*38e8c45fSAndroid Build Coastguard Worker     // Make sure the EGL state is the same as in previous calls.
240*38e8c45fSAndroid Build Coastguard Worker     status_t err = checkAndUpdateEglStateLocked();
241*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
242*38e8c45fSAndroid Build Coastguard Worker         return err;
243*38e8c45fSAndroid Build Coastguard Worker     }
244*38e8c45fSAndroid Build Coastguard Worker 
245*38e8c45fSAndroid Build Coastguard Worker     BufferItem item;
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker     // Acquire the next buffer.
248*38e8c45fSAndroid Build Coastguard Worker     // In asynchronous mode the list is guaranteed to be one buffer
249*38e8c45fSAndroid Build Coastguard Worker     // deep, while in synchronous mode we use the oldest buffer.
250*38e8c45fSAndroid Build Coastguard Worker     err = acquireBufferLocked(&item, 0);
251*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
252*38e8c45fSAndroid Build Coastguard Worker         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
253*38e8c45fSAndroid Build Coastguard Worker             // We always bind the texture even if we don't update its contents.
254*38e8c45fSAndroid Build Coastguard Worker             GLC_LOGV("updateTexImage: no buffers were available");
255*38e8c45fSAndroid Build Coastguard Worker             glBindTexture(mTexTarget, mTexName);
256*38e8c45fSAndroid Build Coastguard Worker             err = NO_ERROR;
257*38e8c45fSAndroid Build Coastguard Worker         } else {
258*38e8c45fSAndroid Build Coastguard Worker             GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
259*38e8c45fSAndroid Build Coastguard Worker                 strerror(-err), err);
260*38e8c45fSAndroid Build Coastguard Worker         }
261*38e8c45fSAndroid Build Coastguard Worker         return err;
262*38e8c45fSAndroid Build Coastguard Worker     }
263*38e8c45fSAndroid Build Coastguard Worker 
264*38e8c45fSAndroid Build Coastguard Worker     // Release the previous buffer.
265*38e8c45fSAndroid Build Coastguard Worker     err = updateAndReleaseLocked(item);
266*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
267*38e8c45fSAndroid Build Coastguard Worker         // We always bind the texture.
268*38e8c45fSAndroid Build Coastguard Worker         glBindTexture(mTexTarget, mTexName);
269*38e8c45fSAndroid Build Coastguard Worker         return err;
270*38e8c45fSAndroid Build Coastguard Worker     }
271*38e8c45fSAndroid Build Coastguard Worker 
272*38e8c45fSAndroid Build Coastguard Worker     // Bind the new buffer to the GL texture, and wait until it's ready.
273*38e8c45fSAndroid Build Coastguard Worker     return bindTextureImageLocked();
274*38e8c45fSAndroid Build Coastguard Worker }
275*38e8c45fSAndroid Build Coastguard Worker 
276*38e8c45fSAndroid Build Coastguard Worker 
releaseTexImage()277*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::releaseTexImage() {
278*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
279*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("releaseTexImage");
280*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
281*38e8c45fSAndroid Build Coastguard Worker 
282*38e8c45fSAndroid Build Coastguard Worker     if (mAbandoned) {
283*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
284*38e8c45fSAndroid Build Coastguard Worker         return NO_INIT;
285*38e8c45fSAndroid Build Coastguard Worker     }
286*38e8c45fSAndroid Build Coastguard Worker 
287*38e8c45fSAndroid Build Coastguard Worker     // Make sure the EGL state is the same as in previous calls.
288*38e8c45fSAndroid Build Coastguard Worker     status_t err = NO_ERROR;
289*38e8c45fSAndroid Build Coastguard Worker 
290*38e8c45fSAndroid Build Coastguard Worker     if (mAttached) {
291*38e8c45fSAndroid Build Coastguard Worker         err = checkAndUpdateEglStateLocked(true);
292*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
293*38e8c45fSAndroid Build Coastguard Worker             return err;
294*38e8c45fSAndroid Build Coastguard Worker         }
295*38e8c45fSAndroid Build Coastguard Worker     } else {
296*38e8c45fSAndroid Build Coastguard Worker         // if we're detached, no need to validate EGL's state -- we won't use it.
297*38e8c45fSAndroid Build Coastguard Worker     }
298*38e8c45fSAndroid Build Coastguard Worker 
299*38e8c45fSAndroid Build Coastguard Worker     // Update the GLConsumer state.
300*38e8c45fSAndroid Build Coastguard Worker     int buf = mCurrentTexture;
301*38e8c45fSAndroid Build Coastguard Worker     if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
302*38e8c45fSAndroid Build Coastguard Worker 
303*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
304*38e8c45fSAndroid Build Coastguard Worker 
305*38e8c45fSAndroid Build Coastguard Worker         if (mAttached) {
306*38e8c45fSAndroid Build Coastguard Worker             // Do whatever sync ops we need to do before releasing the slot.
307*38e8c45fSAndroid Build Coastguard Worker             err = syncForReleaseLocked(mEglDisplay);
308*38e8c45fSAndroid Build Coastguard Worker             if (err != NO_ERROR) {
309*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
310*38e8c45fSAndroid Build Coastguard Worker                 return err;
311*38e8c45fSAndroid Build Coastguard Worker             }
312*38e8c45fSAndroid Build Coastguard Worker         } else {
313*38e8c45fSAndroid Build Coastguard Worker             // if we're detached, we just use the fence that was created in detachFromContext()
314*38e8c45fSAndroid Build Coastguard Worker             // so... basically, nothing more to do here.
315*38e8c45fSAndroid Build Coastguard Worker         }
316*38e8c45fSAndroid Build Coastguard Worker 
317*38e8c45fSAndroid Build Coastguard Worker         err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer);
318*38e8c45fSAndroid Build Coastguard Worker         if (err < NO_ERROR) {
319*38e8c45fSAndroid Build Coastguard Worker             GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
320*38e8c45fSAndroid Build Coastguard Worker                     strerror(-err), err);
321*38e8c45fSAndroid Build Coastguard Worker             return err;
322*38e8c45fSAndroid Build Coastguard Worker         }
323*38e8c45fSAndroid Build Coastguard Worker 
324*38e8c45fSAndroid Build Coastguard Worker         if (mReleasedTexImage == nullptr) {
325*38e8c45fSAndroid Build Coastguard Worker             mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
326*38e8c45fSAndroid Build Coastguard Worker         }
327*38e8c45fSAndroid Build Coastguard Worker 
328*38e8c45fSAndroid Build Coastguard Worker         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
329*38e8c45fSAndroid Build Coastguard Worker         mCurrentTextureImage = mReleasedTexImage;
330*38e8c45fSAndroid Build Coastguard Worker         mCurrentCrop.makeInvalid();
331*38e8c45fSAndroid Build Coastguard Worker         mCurrentTransform = 0;
332*38e8c45fSAndroid Build Coastguard Worker         mCurrentTimestamp = 0;
333*38e8c45fSAndroid Build Coastguard Worker         mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
334*38e8c45fSAndroid Build Coastguard Worker         mCurrentFence = Fence::NO_FENCE;
335*38e8c45fSAndroid Build Coastguard Worker         mCurrentFenceTime = FenceTime::NO_FENCE;
336*38e8c45fSAndroid Build Coastguard Worker 
337*38e8c45fSAndroid Build Coastguard Worker         if (mAttached) {
338*38e8c45fSAndroid Build Coastguard Worker             // This binds a buffer placeholder (mReleasedTexImage).
339*38e8c45fSAndroid Build Coastguard Worker             status_t result = bindTextureImageLocked();
340*38e8c45fSAndroid Build Coastguard Worker             if (result != NO_ERROR) {
341*38e8c45fSAndroid Build Coastguard Worker                 return result;
342*38e8c45fSAndroid Build Coastguard Worker             }
343*38e8c45fSAndroid Build Coastguard Worker         } else {
344*38e8c45fSAndroid Build Coastguard Worker             // detached, don't touch the texture (and we may not even have an
345*38e8c45fSAndroid Build Coastguard Worker             // EGLDisplay here.
346*38e8c45fSAndroid Build Coastguard Worker         }
347*38e8c45fSAndroid Build Coastguard Worker     }
348*38e8c45fSAndroid Build Coastguard Worker 
349*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
350*38e8c45fSAndroid Build Coastguard Worker }
351*38e8c45fSAndroid Build Coastguard Worker 
getDebugTexImageBuffer()352*38e8c45fSAndroid Build Coastguard Worker sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
353*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock _l(sStaticInitLock);
354*38e8c45fSAndroid Build Coastguard Worker     if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
355*38e8c45fSAndroid Build Coastguard Worker         // The first time, create the debug texture in case the application
356*38e8c45fSAndroid Build Coastguard Worker         // continues to use it.
357*38e8c45fSAndroid Build Coastguard Worker         sp<GraphicBuffer> buffer = new GraphicBuffer(
358*38e8c45fSAndroid Build Coastguard Worker                 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
359*38e8c45fSAndroid Build Coastguard Worker                 DEFAULT_USAGE_FLAGS | GraphicBuffer::USAGE_SW_WRITE_RARELY,
360*38e8c45fSAndroid Build Coastguard Worker                 "[GLConsumer debug texture]");
361*38e8c45fSAndroid Build Coastguard Worker         uint32_t* bits;
362*38e8c45fSAndroid Build Coastguard Worker         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
363*38e8c45fSAndroid Build Coastguard Worker         uint32_t stride = buffer->getStride();
364*38e8c45fSAndroid Build Coastguard Worker         uint32_t height = buffer->getHeight();
365*38e8c45fSAndroid Build Coastguard Worker         memset(bits, 0, stride * height * 4);
366*38e8c45fSAndroid Build Coastguard Worker         for (uint32_t y = 0; y < kDebugData.height; y++) {
367*38e8c45fSAndroid Build Coastguard Worker             for (uint32_t x = 0; x < kDebugData.width; x++) {
368*38e8c45fSAndroid Build Coastguard Worker                 bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
369*38e8c45fSAndroid Build Coastguard Worker                     0xFF000000 : 0xFFFFFFFF;
370*38e8c45fSAndroid Build Coastguard Worker             }
371*38e8c45fSAndroid Build Coastguard Worker             bits += stride;
372*38e8c45fSAndroid Build Coastguard Worker         }
373*38e8c45fSAndroid Build Coastguard Worker         buffer->unlock();
374*38e8c45fSAndroid Build Coastguard Worker         sReleasedTexImageBuffer = buffer;
375*38e8c45fSAndroid Build Coastguard Worker     }
376*38e8c45fSAndroid Build Coastguard Worker     return sReleasedTexImageBuffer;
377*38e8c45fSAndroid Build Coastguard Worker }
378*38e8c45fSAndroid Build Coastguard Worker 
acquireBufferLocked(BufferItem * item,nsecs_t presentWhen,uint64_t maxFrameNumber)379*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::acquireBufferLocked(BufferItem *item,
380*38e8c45fSAndroid Build Coastguard Worker         nsecs_t presentWhen, uint64_t maxFrameNumber) {
381*38e8c45fSAndroid Build Coastguard Worker     status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
382*38e8c45fSAndroid Build Coastguard Worker             maxFrameNumber);
383*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
384*38e8c45fSAndroid Build Coastguard Worker         return err;
385*38e8c45fSAndroid Build Coastguard Worker     }
386*38e8c45fSAndroid Build Coastguard Worker 
387*38e8c45fSAndroid Build Coastguard Worker     // If item->mGraphicBuffer is not null, this buffer has not been acquired
388*38e8c45fSAndroid Build Coastguard Worker     // before, so any prior EglImage created is using a stale buffer. This
389*38e8c45fSAndroid Build Coastguard Worker     // replaces any old EglImage with a new one (using the new buffer).
390*38e8c45fSAndroid Build Coastguard Worker     if (item->mGraphicBuffer != nullptr) {
391*38e8c45fSAndroid Build Coastguard Worker         int slot = item->mSlot;
392*38e8c45fSAndroid Build Coastguard Worker         mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
393*38e8c45fSAndroid Build Coastguard Worker     }
394*38e8c45fSAndroid Build Coastguard Worker 
395*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
396*38e8c45fSAndroid Build Coastguard Worker }
397*38e8c45fSAndroid Build Coastguard Worker 
releaseBufferLocked(int buf,sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)398*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::releaseBufferLocked(int buf,
399*38e8c45fSAndroid Build Coastguard Worker         sp<GraphicBuffer> graphicBuffer,
400*38e8c45fSAndroid Build Coastguard Worker         EGLDisplay display, EGLSyncKHR eglFence) {
401*38e8c45fSAndroid Build Coastguard Worker     // release the buffer if it hasn't already been discarded by the
402*38e8c45fSAndroid Build Coastguard Worker     // BufferQueue. This can happen, for example, when the producer of this
403*38e8c45fSAndroid Build Coastguard Worker     // buffer has reallocated the original buffer slot after this buffer
404*38e8c45fSAndroid Build Coastguard Worker     // was acquired.
405*38e8c45fSAndroid Build Coastguard Worker     status_t err = ConsumerBase::releaseBufferLocked(
406*38e8c45fSAndroid Build Coastguard Worker             buf, graphicBuffer, display, eglFence);
407*38e8c45fSAndroid Build Coastguard Worker     mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
408*38e8c45fSAndroid Build Coastguard Worker     return err;
409*38e8c45fSAndroid Build Coastguard Worker }
410*38e8c45fSAndroid Build Coastguard Worker 
updateAndReleaseLocked(const BufferItem & item,PendingRelease * pendingRelease)411*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
412*38e8c45fSAndroid Build Coastguard Worker         PendingRelease* pendingRelease)
413*38e8c45fSAndroid Build Coastguard Worker {
414*38e8c45fSAndroid Build Coastguard Worker     status_t err = NO_ERROR;
415*38e8c45fSAndroid Build Coastguard Worker 
416*38e8c45fSAndroid Build Coastguard Worker     int slot = item.mSlot;
417*38e8c45fSAndroid Build Coastguard Worker 
418*38e8c45fSAndroid Build Coastguard Worker     if (!mAttached) {
419*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
420*38e8c45fSAndroid Build Coastguard Worker                 "ES context");
421*38e8c45fSAndroid Build Coastguard Worker         releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
422*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
423*38e8c45fSAndroid Build Coastguard Worker     }
424*38e8c45fSAndroid Build Coastguard Worker 
425*38e8c45fSAndroid Build Coastguard Worker     // Confirm state.
426*38e8c45fSAndroid Build Coastguard Worker     err = checkAndUpdateEglStateLocked();
427*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
428*38e8c45fSAndroid Build Coastguard Worker         releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
429*38e8c45fSAndroid Build Coastguard Worker         return err;
430*38e8c45fSAndroid Build Coastguard Worker     }
431*38e8c45fSAndroid Build Coastguard Worker 
432*38e8c45fSAndroid Build Coastguard Worker     // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
433*38e8c45fSAndroid Build Coastguard Worker     // if nessessary, for the gralloc buffer currently in the slot in
434*38e8c45fSAndroid Build Coastguard Worker     // ConsumerBase.
435*38e8c45fSAndroid Build Coastguard Worker     // We may have to do this even when item.mGraphicBuffer == NULL (which
436*38e8c45fSAndroid Build Coastguard Worker     // means the buffer was previously acquired).
437*38e8c45fSAndroid Build Coastguard Worker     err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay);
438*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
439*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
440*38e8c45fSAndroid Build Coastguard Worker                 mEglDisplay, slot);
441*38e8c45fSAndroid Build Coastguard Worker         releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
442*38e8c45fSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
443*38e8c45fSAndroid Build Coastguard Worker     }
444*38e8c45fSAndroid Build Coastguard Worker 
445*38e8c45fSAndroid Build Coastguard Worker     // Do whatever sync ops we need to do before releasing the old slot.
446*38e8c45fSAndroid Build Coastguard Worker     if (slot != mCurrentTexture) {
447*38e8c45fSAndroid Build Coastguard Worker         err = syncForReleaseLocked(mEglDisplay);
448*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
449*38e8c45fSAndroid Build Coastguard Worker             // Release the buffer we just acquired.  It's not safe to
450*38e8c45fSAndroid Build Coastguard Worker             // release the old buffer, so instead we just drop the new frame.
451*38e8c45fSAndroid Build Coastguard Worker             // As we are still under lock since acquireBuffer, it is safe to
452*38e8c45fSAndroid Build Coastguard Worker             // release by slot.
453*38e8c45fSAndroid Build Coastguard Worker             releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
454*38e8c45fSAndroid Build Coastguard Worker             return err;
455*38e8c45fSAndroid Build Coastguard Worker         }
456*38e8c45fSAndroid Build Coastguard Worker     }
457*38e8c45fSAndroid Build Coastguard Worker 
458*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
459*38e8c45fSAndroid Build Coastguard Worker             mCurrentTexture, mCurrentTextureImage != nullptr ?
460*38e8c45fSAndroid Build Coastguard Worker                     mCurrentTextureImage->graphicBufferHandle() : nullptr,
461*38e8c45fSAndroid Build Coastguard Worker             slot, mSlots[slot].mGraphicBuffer->handle);
462*38e8c45fSAndroid Build Coastguard Worker 
463*38e8c45fSAndroid Build Coastguard Worker     // Hang onto the pointer so that it isn't freed in the call to
464*38e8c45fSAndroid Build Coastguard Worker     // releaseBufferLocked() if we're in shared buffer mode and both buffers are
465*38e8c45fSAndroid Build Coastguard Worker     // the same.
466*38e8c45fSAndroid Build Coastguard Worker     sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
467*38e8c45fSAndroid Build Coastguard Worker 
468*38e8c45fSAndroid Build Coastguard Worker     // release old buffer
469*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
470*38e8c45fSAndroid Build Coastguard Worker         if (pendingRelease == nullptr) {
471*38e8c45fSAndroid Build Coastguard Worker             status_t status = releaseBufferLocked(
472*38e8c45fSAndroid Build Coastguard Worker                     mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
473*38e8c45fSAndroid Build Coastguard Worker                     mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
474*38e8c45fSAndroid Build Coastguard Worker             if (status < NO_ERROR) {
475*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
476*38e8c45fSAndroid Build Coastguard Worker                         strerror(-status), status);
477*38e8c45fSAndroid Build Coastguard Worker                 err = status;
478*38e8c45fSAndroid Build Coastguard Worker                 // keep going, with error raised [?]
479*38e8c45fSAndroid Build Coastguard Worker             }
480*38e8c45fSAndroid Build Coastguard Worker         } else {
481*38e8c45fSAndroid Build Coastguard Worker             pendingRelease->currentTexture = mCurrentTexture;
482*38e8c45fSAndroid Build Coastguard Worker             pendingRelease->graphicBuffer =
483*38e8c45fSAndroid Build Coastguard Worker                     mCurrentTextureImage->graphicBuffer();
484*38e8c45fSAndroid Build Coastguard Worker             pendingRelease->display = mEglDisplay;
485*38e8c45fSAndroid Build Coastguard Worker             pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
486*38e8c45fSAndroid Build Coastguard Worker             pendingRelease->isPending = true;
487*38e8c45fSAndroid Build Coastguard Worker         }
488*38e8c45fSAndroid Build Coastguard Worker     }
489*38e8c45fSAndroid Build Coastguard Worker 
490*38e8c45fSAndroid Build Coastguard Worker     // Update the GLConsumer state.
491*38e8c45fSAndroid Build Coastguard Worker     mCurrentTexture = slot;
492*38e8c45fSAndroid Build Coastguard Worker     mCurrentTextureImage = nextTextureImage;
493*38e8c45fSAndroid Build Coastguard Worker     mCurrentCrop = item.mCrop;
494*38e8c45fSAndroid Build Coastguard Worker     mCurrentTransform = item.mTransform;
495*38e8c45fSAndroid Build Coastguard Worker     mCurrentScalingMode = item.mScalingMode;
496*38e8c45fSAndroid Build Coastguard Worker     mCurrentTimestamp = item.mTimestamp;
497*38e8c45fSAndroid Build Coastguard Worker     mCurrentDataSpace = item.mDataSpace;
498*38e8c45fSAndroid Build Coastguard Worker     mCurrentFence = item.mFence;
499*38e8c45fSAndroid Build Coastguard Worker     mCurrentFenceTime = item.mFenceTime;
500*38e8c45fSAndroid Build Coastguard Worker     mCurrentFrameNumber = item.mFrameNumber;
501*38e8c45fSAndroid Build Coastguard Worker 
502*38e8c45fSAndroid Build Coastguard Worker     computeCurrentTransformMatrixLocked();
503*38e8c45fSAndroid Build Coastguard Worker 
504*38e8c45fSAndroid Build Coastguard Worker     return err;
505*38e8c45fSAndroid Build Coastguard Worker }
506*38e8c45fSAndroid Build Coastguard Worker 
bindTextureImageLocked()507*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::bindTextureImageLocked() {
508*38e8c45fSAndroid Build Coastguard Worker     if (mEglDisplay == EGL_NO_DISPLAY) {
509*38e8c45fSAndroid Build Coastguard Worker         ALOGE("bindTextureImage: invalid display");
510*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
511*38e8c45fSAndroid Build Coastguard Worker     }
512*38e8c45fSAndroid Build Coastguard Worker 
513*38e8c45fSAndroid Build Coastguard Worker     GLenum error;
514*38e8c45fSAndroid Build Coastguard Worker     while ((error = glGetError()) != GL_NO_ERROR) {
515*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
516*38e8c45fSAndroid Build Coastguard Worker     }
517*38e8c45fSAndroid Build Coastguard Worker 
518*38e8c45fSAndroid Build Coastguard Worker     glBindTexture(mTexTarget, mTexName);
519*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
520*38e8c45fSAndroid Build Coastguard Worker             mCurrentTextureImage == nullptr) {
521*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("bindTextureImage: no currently-bound texture");
522*38e8c45fSAndroid Build Coastguard Worker         return NO_INIT;
523*38e8c45fSAndroid Build Coastguard Worker     }
524*38e8c45fSAndroid Build Coastguard Worker 
525*38e8c45fSAndroid Build Coastguard Worker     status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay);
526*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
527*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
528*38e8c45fSAndroid Build Coastguard Worker                 mEglDisplay, mCurrentTexture);
529*38e8c45fSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
530*38e8c45fSAndroid Build Coastguard Worker     }
531*38e8c45fSAndroid Build Coastguard Worker     mCurrentTextureImage->bindToTextureTarget(mTexTarget);
532*38e8c45fSAndroid Build Coastguard Worker 
533*38e8c45fSAndroid Build Coastguard Worker     // In the rare case that the display is terminated and then initialized
534*38e8c45fSAndroid Build Coastguard Worker     // again, we can't detect that the display changed (it didn't), but the
535*38e8c45fSAndroid Build Coastguard Worker     // image is invalid. In this case, repeat the exact same steps while
536*38e8c45fSAndroid Build Coastguard Worker     // forcing the creation of a new image.
537*38e8c45fSAndroid Build Coastguard Worker     if ((error = glGetError()) != GL_NO_ERROR) {
538*38e8c45fSAndroid Build Coastguard Worker         glBindTexture(mTexTarget, mTexName);
539*38e8c45fSAndroid Build Coastguard Worker         status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, true);
540*38e8c45fSAndroid Build Coastguard Worker         if (result != NO_ERROR) {
541*38e8c45fSAndroid Build Coastguard Worker             GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
542*38e8c45fSAndroid Build Coastguard Worker                     mEglDisplay, mCurrentTexture);
543*38e8c45fSAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
544*38e8c45fSAndroid Build Coastguard Worker         }
545*38e8c45fSAndroid Build Coastguard Worker         mCurrentTextureImage->bindToTextureTarget(mTexTarget);
546*38e8c45fSAndroid Build Coastguard Worker         if ((error = glGetError()) != GL_NO_ERROR) {
547*38e8c45fSAndroid Build Coastguard Worker             GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
548*38e8c45fSAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
549*38e8c45fSAndroid Build Coastguard Worker         }
550*38e8c45fSAndroid Build Coastguard Worker     }
551*38e8c45fSAndroid Build Coastguard Worker 
552*38e8c45fSAndroid Build Coastguard Worker     // Wait for the new buffer to be ready.
553*38e8c45fSAndroid Build Coastguard Worker     return doGLFenceWaitLocked();
554*38e8c45fSAndroid Build Coastguard Worker }
555*38e8c45fSAndroid Build Coastguard Worker 
checkAndUpdateEglStateLocked(bool contextCheck)556*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
557*38e8c45fSAndroid Build Coastguard Worker     EGLDisplay dpy = eglGetCurrentDisplay();
558*38e8c45fSAndroid Build Coastguard Worker     EGLContext ctx = eglGetCurrentContext();
559*38e8c45fSAndroid Build Coastguard Worker 
560*38e8c45fSAndroid Build Coastguard Worker     if (!contextCheck) {
561*38e8c45fSAndroid Build Coastguard Worker         // if this is the first time we're called, mEglDisplay/mEglContext have
562*38e8c45fSAndroid Build Coastguard Worker         // never been set, so don't error out (below).
563*38e8c45fSAndroid Build Coastguard Worker         if (mEglDisplay == EGL_NO_DISPLAY) {
564*38e8c45fSAndroid Build Coastguard Worker             mEglDisplay = dpy;
565*38e8c45fSAndroid Build Coastguard Worker         }
566*38e8c45fSAndroid Build Coastguard Worker         if (mEglContext == EGL_NO_CONTEXT) {
567*38e8c45fSAndroid Build Coastguard Worker             mEglContext = ctx;
568*38e8c45fSAndroid Build Coastguard Worker         }
569*38e8c45fSAndroid Build Coastguard Worker     }
570*38e8c45fSAndroid Build Coastguard Worker 
571*38e8c45fSAndroid Build Coastguard Worker     if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
572*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
573*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
574*38e8c45fSAndroid Build Coastguard Worker     }
575*38e8c45fSAndroid Build Coastguard Worker 
576*38e8c45fSAndroid Build Coastguard Worker     if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
577*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
578*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
579*38e8c45fSAndroid Build Coastguard Worker     }
580*38e8c45fSAndroid Build Coastguard Worker 
581*38e8c45fSAndroid Build Coastguard Worker     mEglDisplay = dpy;
582*38e8c45fSAndroid Build Coastguard Worker     mEglContext = ctx;
583*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
584*38e8c45fSAndroid Build Coastguard Worker }
585*38e8c45fSAndroid Build Coastguard Worker 
setReleaseFence(const sp<Fence> & fence)586*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
587*38e8c45fSAndroid Build Coastguard Worker     if (fence->isValid() &&
588*38e8c45fSAndroid Build Coastguard Worker             mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
589*38e8c45fSAndroid Build Coastguard Worker         status_t err = addReleaseFence(mCurrentTexture,
590*38e8c45fSAndroid Build Coastguard Worker                 mCurrentTextureImage->graphicBuffer(), fence);
591*38e8c45fSAndroid Build Coastguard Worker         if (err != OK) {
592*38e8c45fSAndroid Build Coastguard Worker             GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
593*38e8c45fSAndroid Build Coastguard Worker                     strerror(-err), err);
594*38e8c45fSAndroid Build Coastguard Worker         }
595*38e8c45fSAndroid Build Coastguard Worker     }
596*38e8c45fSAndroid Build Coastguard Worker }
597*38e8c45fSAndroid Build Coastguard Worker 
detachFromContext()598*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::detachFromContext() {
599*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
600*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("detachFromContext");
601*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
602*38e8c45fSAndroid Build Coastguard Worker 
603*38e8c45fSAndroid Build Coastguard Worker     if (mAbandoned) {
604*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("detachFromContext: abandoned GLConsumer");
605*38e8c45fSAndroid Build Coastguard Worker         return NO_INIT;
606*38e8c45fSAndroid Build Coastguard Worker     }
607*38e8c45fSAndroid Build Coastguard Worker 
608*38e8c45fSAndroid Build Coastguard Worker     if (!mAttached) {
609*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
610*38e8c45fSAndroid Build Coastguard Worker                 "context");
611*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
612*38e8c45fSAndroid Build Coastguard Worker     }
613*38e8c45fSAndroid Build Coastguard Worker 
614*38e8c45fSAndroid Build Coastguard Worker     EGLDisplay dpy = eglGetCurrentDisplay();
615*38e8c45fSAndroid Build Coastguard Worker     EGLContext ctx = eglGetCurrentContext();
616*38e8c45fSAndroid Build Coastguard Worker 
617*38e8c45fSAndroid Build Coastguard Worker     if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
618*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("detachFromContext: invalid current EGLDisplay");
619*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
620*38e8c45fSAndroid Build Coastguard Worker     }
621*38e8c45fSAndroid Build Coastguard Worker 
622*38e8c45fSAndroid Build Coastguard Worker     if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
623*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("detachFromContext: invalid current EGLContext");
624*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
625*38e8c45fSAndroid Build Coastguard Worker     }
626*38e8c45fSAndroid Build Coastguard Worker 
627*38e8c45fSAndroid Build Coastguard Worker     if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
628*38e8c45fSAndroid Build Coastguard Worker         status_t err = syncForReleaseLocked(dpy);
629*38e8c45fSAndroid Build Coastguard Worker         if (err != OK) {
630*38e8c45fSAndroid Build Coastguard Worker             return err;
631*38e8c45fSAndroid Build Coastguard Worker         }
632*38e8c45fSAndroid Build Coastguard Worker 
633*38e8c45fSAndroid Build Coastguard Worker         glDeleteTextures(1, &mTexName);
634*38e8c45fSAndroid Build Coastguard Worker     }
635*38e8c45fSAndroid Build Coastguard Worker 
636*38e8c45fSAndroid Build Coastguard Worker     mEglDisplay = EGL_NO_DISPLAY;
637*38e8c45fSAndroid Build Coastguard Worker     mEglContext = EGL_NO_CONTEXT;
638*38e8c45fSAndroid Build Coastguard Worker     mAttached = false;
639*38e8c45fSAndroid Build Coastguard Worker 
640*38e8c45fSAndroid Build Coastguard Worker     return OK;
641*38e8c45fSAndroid Build Coastguard Worker }
642*38e8c45fSAndroid Build Coastguard Worker 
attachToContext(uint32_t tex)643*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::attachToContext(uint32_t tex) {
644*38e8c45fSAndroid Build Coastguard Worker     ATRACE_CALL();
645*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("attachToContext");
646*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
647*38e8c45fSAndroid Build Coastguard Worker 
648*38e8c45fSAndroid Build Coastguard Worker     if (mAbandoned) {
649*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("attachToContext: abandoned GLConsumer");
650*38e8c45fSAndroid Build Coastguard Worker         return NO_INIT;
651*38e8c45fSAndroid Build Coastguard Worker     }
652*38e8c45fSAndroid Build Coastguard Worker 
653*38e8c45fSAndroid Build Coastguard Worker     if (mAttached) {
654*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("attachToContext: GLConsumer is already attached to a "
655*38e8c45fSAndroid Build Coastguard Worker                 "context");
656*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
657*38e8c45fSAndroid Build Coastguard Worker     }
658*38e8c45fSAndroid Build Coastguard Worker 
659*38e8c45fSAndroid Build Coastguard Worker     EGLDisplay dpy = eglGetCurrentDisplay();
660*38e8c45fSAndroid Build Coastguard Worker     EGLContext ctx = eglGetCurrentContext();
661*38e8c45fSAndroid Build Coastguard Worker 
662*38e8c45fSAndroid Build Coastguard Worker     if (dpy == EGL_NO_DISPLAY) {
663*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("attachToContext: invalid current EGLDisplay");
664*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
665*38e8c45fSAndroid Build Coastguard Worker     }
666*38e8c45fSAndroid Build Coastguard Worker 
667*38e8c45fSAndroid Build Coastguard Worker     if (ctx == EGL_NO_CONTEXT) {
668*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("attachToContext: invalid current EGLContext");
669*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
670*38e8c45fSAndroid Build Coastguard Worker     }
671*38e8c45fSAndroid Build Coastguard Worker 
672*38e8c45fSAndroid Build Coastguard Worker     // We need to bind the texture regardless of whether there's a current
673*38e8c45fSAndroid Build Coastguard Worker     // buffer.
674*38e8c45fSAndroid Build Coastguard Worker     glBindTexture(mTexTarget, GLuint(tex));
675*38e8c45fSAndroid Build Coastguard Worker 
676*38e8c45fSAndroid Build Coastguard Worker     mEglDisplay = dpy;
677*38e8c45fSAndroid Build Coastguard Worker     mEglContext = ctx;
678*38e8c45fSAndroid Build Coastguard Worker     mTexName = tex;
679*38e8c45fSAndroid Build Coastguard Worker     mAttached = true;
680*38e8c45fSAndroid Build Coastguard Worker 
681*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentTextureImage != nullptr) {
682*38e8c45fSAndroid Build Coastguard Worker         // This may wait for a buffer a second time. This is likely required if
683*38e8c45fSAndroid Build Coastguard Worker         // this is a different context, since otherwise the wait could be skipped
684*38e8c45fSAndroid Build Coastguard Worker         // by bouncing through another context. For the same context the extra
685*38e8c45fSAndroid Build Coastguard Worker         // wait is redundant.
686*38e8c45fSAndroid Build Coastguard Worker         status_t err =  bindTextureImageLocked();
687*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
688*38e8c45fSAndroid Build Coastguard Worker             return err;
689*38e8c45fSAndroid Build Coastguard Worker         }
690*38e8c45fSAndroid Build Coastguard Worker     }
691*38e8c45fSAndroid Build Coastguard Worker 
692*38e8c45fSAndroid Build Coastguard Worker     return OK;
693*38e8c45fSAndroid Build Coastguard Worker }
694*38e8c45fSAndroid Build Coastguard Worker 
695*38e8c45fSAndroid Build Coastguard Worker 
syncForReleaseLocked(EGLDisplay dpy)696*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
697*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("syncForReleaseLocked");
698*38e8c45fSAndroid Build Coastguard Worker 
699*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
700*38e8c45fSAndroid Build Coastguard Worker         if (SyncFeatures::getInstance().useNativeFenceSync()) {
701*38e8c45fSAndroid Build Coastguard Worker             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
702*38e8c45fSAndroid Build Coastguard Worker                     EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
703*38e8c45fSAndroid Build Coastguard Worker             if (sync == EGL_NO_SYNC_KHR) {
704*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
705*38e8c45fSAndroid Build Coastguard Worker                         eglGetError());
706*38e8c45fSAndroid Build Coastguard Worker                 return UNKNOWN_ERROR;
707*38e8c45fSAndroid Build Coastguard Worker             }
708*38e8c45fSAndroid Build Coastguard Worker             glFlush();
709*38e8c45fSAndroid Build Coastguard Worker             int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
710*38e8c45fSAndroid Build Coastguard Worker             eglDestroySyncKHR(dpy, sync);
711*38e8c45fSAndroid Build Coastguard Worker             if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
712*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
713*38e8c45fSAndroid Build Coastguard Worker                         "fd: %#x", eglGetError());
714*38e8c45fSAndroid Build Coastguard Worker                 return UNKNOWN_ERROR;
715*38e8c45fSAndroid Build Coastguard Worker             }
716*38e8c45fSAndroid Build Coastguard Worker             sp<Fence> fence(new Fence(fenceFd));
717*38e8c45fSAndroid Build Coastguard Worker             status_t err = addReleaseFenceLocked(mCurrentTexture,
718*38e8c45fSAndroid Build Coastguard Worker                     mCurrentTextureImage->graphicBuffer(), fence);
719*38e8c45fSAndroid Build Coastguard Worker             if (err != OK) {
720*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("syncForReleaseLocked: error adding release fence: "
721*38e8c45fSAndroid Build Coastguard Worker                         "%s (%d)", strerror(-err), err);
722*38e8c45fSAndroid Build Coastguard Worker                 return err;
723*38e8c45fSAndroid Build Coastguard Worker             }
724*38e8c45fSAndroid Build Coastguard Worker         } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
725*38e8c45fSAndroid Build Coastguard Worker             EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
726*38e8c45fSAndroid Build Coastguard Worker             if (fence != EGL_NO_SYNC_KHR) {
727*38e8c45fSAndroid Build Coastguard Worker                 // There is already a fence for the current slot.  We need to
728*38e8c45fSAndroid Build Coastguard Worker                 // wait on that before replacing it with another fence to
729*38e8c45fSAndroid Build Coastguard Worker                 // ensure that all outstanding buffer accesses have completed
730*38e8c45fSAndroid Build Coastguard Worker                 // before the producer accesses it.
731*38e8c45fSAndroid Build Coastguard Worker                 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
732*38e8c45fSAndroid Build Coastguard Worker                 if (result == EGL_FALSE) {
733*38e8c45fSAndroid Build Coastguard Worker                     GLC_LOGE("syncForReleaseLocked: error waiting for previous "
734*38e8c45fSAndroid Build Coastguard Worker                             "fence: %#x", eglGetError());
735*38e8c45fSAndroid Build Coastguard Worker                     return UNKNOWN_ERROR;
736*38e8c45fSAndroid Build Coastguard Worker                 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
737*38e8c45fSAndroid Build Coastguard Worker                     GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
738*38e8c45fSAndroid Build Coastguard Worker                             "fence");
739*38e8c45fSAndroid Build Coastguard Worker                     return TIMED_OUT;
740*38e8c45fSAndroid Build Coastguard Worker                 }
741*38e8c45fSAndroid Build Coastguard Worker                 eglDestroySyncKHR(dpy, fence);
742*38e8c45fSAndroid Build Coastguard Worker             }
743*38e8c45fSAndroid Build Coastguard Worker 
744*38e8c45fSAndroid Build Coastguard Worker             // Create a fence for the outstanding accesses in the current
745*38e8c45fSAndroid Build Coastguard Worker             // OpenGL ES context.
746*38e8c45fSAndroid Build Coastguard Worker             fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
747*38e8c45fSAndroid Build Coastguard Worker             if (fence == EGL_NO_SYNC_KHR) {
748*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
749*38e8c45fSAndroid Build Coastguard Worker                         eglGetError());
750*38e8c45fSAndroid Build Coastguard Worker                 return UNKNOWN_ERROR;
751*38e8c45fSAndroid Build Coastguard Worker             }
752*38e8c45fSAndroid Build Coastguard Worker             glFlush();
753*38e8c45fSAndroid Build Coastguard Worker             mEglSlots[mCurrentTexture].mEglFence = fence;
754*38e8c45fSAndroid Build Coastguard Worker         }
755*38e8c45fSAndroid Build Coastguard Worker     }
756*38e8c45fSAndroid Build Coastguard Worker 
757*38e8c45fSAndroid Build Coastguard Worker     return OK;
758*38e8c45fSAndroid Build Coastguard Worker }
759*38e8c45fSAndroid Build Coastguard Worker 
getCurrentTextureTarget() const760*38e8c45fSAndroid Build Coastguard Worker uint32_t GLConsumer::getCurrentTextureTarget() const {
761*38e8c45fSAndroid Build Coastguard Worker     return mTexTarget;
762*38e8c45fSAndroid Build Coastguard Worker }
763*38e8c45fSAndroid Build Coastguard Worker 
getTransformMatrix(float mtx[16])764*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::getTransformMatrix(float mtx[16]) {
765*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
766*38e8c45fSAndroid Build Coastguard Worker     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
767*38e8c45fSAndroid Build Coastguard Worker }
768*38e8c45fSAndroid Build Coastguard Worker 
setFilteringEnabled(bool enabled)769*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::setFilteringEnabled(bool enabled) {
770*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
771*38e8c45fSAndroid Build Coastguard Worker     if (mAbandoned) {
772*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
773*38e8c45fSAndroid Build Coastguard Worker         return;
774*38e8c45fSAndroid Build Coastguard Worker     }
775*38e8c45fSAndroid Build Coastguard Worker     bool needsRecompute = mFilteringEnabled != enabled;
776*38e8c45fSAndroid Build Coastguard Worker     mFilteringEnabled = enabled;
777*38e8c45fSAndroid Build Coastguard Worker 
778*38e8c45fSAndroid Build Coastguard Worker     if (needsRecompute && mCurrentTextureImage==nullptr) {
779*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
780*38e8c45fSAndroid Build Coastguard Worker     }
781*38e8c45fSAndroid Build Coastguard Worker 
782*38e8c45fSAndroid Build Coastguard Worker     if (needsRecompute && mCurrentTextureImage != nullptr) {
783*38e8c45fSAndroid Build Coastguard Worker         computeCurrentTransformMatrixLocked();
784*38e8c45fSAndroid Build Coastguard Worker     }
785*38e8c45fSAndroid Build Coastguard Worker }
786*38e8c45fSAndroid Build Coastguard Worker 
computeCurrentTransformMatrixLocked()787*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::computeCurrentTransformMatrixLocked() {
788*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("computeCurrentTransformMatrixLocked");
789*38e8c45fSAndroid Build Coastguard Worker     sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
790*38e8c45fSAndroid Build Coastguard Worker             nullptr : mCurrentTextureImage->graphicBuffer();
791*38e8c45fSAndroid Build Coastguard Worker     if (buf == nullptr) {
792*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGD("computeCurrentTransformMatrixLocked: "
793*38e8c45fSAndroid Build Coastguard Worker                 "mCurrentTextureImage is NULL");
794*38e8c45fSAndroid Build Coastguard Worker     }
795*38e8c45fSAndroid Build Coastguard Worker     computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop,
796*38e8c45fSAndroid Build Coastguard Worker         mCurrentTransform, mFilteringEnabled);
797*38e8c45fSAndroid Build Coastguard Worker }
798*38e8c45fSAndroid Build Coastguard Worker 
scaleDownCrop(const Rect & crop,uint32_t bufferWidth,uint32_t bufferHeight)799*38e8c45fSAndroid Build Coastguard Worker Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
800*38e8c45fSAndroid Build Coastguard Worker     Rect outCrop = crop;
801*38e8c45fSAndroid Build Coastguard Worker 
802*38e8c45fSAndroid Build Coastguard Worker     uint32_t newWidth = static_cast<uint32_t>(crop.width());
803*38e8c45fSAndroid Build Coastguard Worker     uint32_t newHeight = static_cast<uint32_t>(crop.height());
804*38e8c45fSAndroid Build Coastguard Worker 
805*38e8c45fSAndroid Build Coastguard Worker     if (newWidth * bufferHeight > newHeight * bufferWidth) {
806*38e8c45fSAndroid Build Coastguard Worker         newWidth = newHeight * bufferWidth / bufferHeight;
807*38e8c45fSAndroid Build Coastguard Worker         ALOGV("too wide: newWidth = %d", newWidth);
808*38e8c45fSAndroid Build Coastguard Worker     } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
809*38e8c45fSAndroid Build Coastguard Worker         newHeight = newWidth * bufferHeight / bufferWidth;
810*38e8c45fSAndroid Build Coastguard Worker         ALOGV("too tall: newHeight = %d", newHeight);
811*38e8c45fSAndroid Build Coastguard Worker     }
812*38e8c45fSAndroid Build Coastguard Worker 
813*38e8c45fSAndroid Build Coastguard Worker     uint32_t currentWidth = static_cast<uint32_t>(crop.width());
814*38e8c45fSAndroid Build Coastguard Worker     uint32_t currentHeight = static_cast<uint32_t>(crop.height());
815*38e8c45fSAndroid Build Coastguard Worker 
816*38e8c45fSAndroid Build Coastguard Worker     // The crop is too wide
817*38e8c45fSAndroid Build Coastguard Worker     if (newWidth < currentWidth) {
818*38e8c45fSAndroid Build Coastguard Worker         uint32_t dw = currentWidth - newWidth;
819*38e8c45fSAndroid Build Coastguard Worker         auto halfdw = dw / 2;
820*38e8c45fSAndroid Build Coastguard Worker         outCrop.left += halfdw;
821*38e8c45fSAndroid Build Coastguard Worker         // Not halfdw because it would subtract 1 too few when dw is odd
822*38e8c45fSAndroid Build Coastguard Worker         outCrop.right -= (dw - halfdw);
823*38e8c45fSAndroid Build Coastguard Worker         // The crop is too tall
824*38e8c45fSAndroid Build Coastguard Worker     } else if (newHeight < currentHeight) {
825*38e8c45fSAndroid Build Coastguard Worker         uint32_t dh = currentHeight - newHeight;
826*38e8c45fSAndroid Build Coastguard Worker         auto halfdh = dh / 2;
827*38e8c45fSAndroid Build Coastguard Worker         outCrop.top += halfdh;
828*38e8c45fSAndroid Build Coastguard Worker         // Not halfdh because it would subtract 1 too few when dh is odd
829*38e8c45fSAndroid Build Coastguard Worker         outCrop.bottom -= (dh - halfdh);
830*38e8c45fSAndroid Build Coastguard Worker     }
831*38e8c45fSAndroid Build Coastguard Worker 
832*38e8c45fSAndroid Build Coastguard Worker     ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
833*38e8c45fSAndroid Build Coastguard Worker             outCrop.left, outCrop.top,
834*38e8c45fSAndroid Build Coastguard Worker             outCrop.right,outCrop.bottom);
835*38e8c45fSAndroid Build Coastguard Worker 
836*38e8c45fSAndroid Build Coastguard Worker     return outCrop;
837*38e8c45fSAndroid Build Coastguard Worker }
838*38e8c45fSAndroid Build Coastguard Worker 
getTimestamp()839*38e8c45fSAndroid Build Coastguard Worker nsecs_t GLConsumer::getTimestamp() {
840*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("getTimestamp");
841*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
842*38e8c45fSAndroid Build Coastguard Worker     return mCurrentTimestamp;
843*38e8c45fSAndroid Build Coastguard Worker }
844*38e8c45fSAndroid Build Coastguard Worker 
getCurrentDataSpace()845*38e8c45fSAndroid Build Coastguard Worker android_dataspace GLConsumer::getCurrentDataSpace() {
846*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("getCurrentDataSpace");
847*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
848*38e8c45fSAndroid Build Coastguard Worker     return mCurrentDataSpace;
849*38e8c45fSAndroid Build Coastguard Worker }
850*38e8c45fSAndroid Build Coastguard Worker 
getFrameNumber()851*38e8c45fSAndroid Build Coastguard Worker uint64_t GLConsumer::getFrameNumber() {
852*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("getFrameNumber");
853*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
854*38e8c45fSAndroid Build Coastguard Worker     return mCurrentFrameNumber;
855*38e8c45fSAndroid Build Coastguard Worker }
856*38e8c45fSAndroid Build Coastguard Worker 
getCurrentBuffer(int * outSlot) const857*38e8c45fSAndroid Build Coastguard Worker sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
858*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
859*38e8c45fSAndroid Build Coastguard Worker 
860*38e8c45fSAndroid Build Coastguard Worker     if (outSlot != nullptr) {
861*38e8c45fSAndroid Build Coastguard Worker         *outSlot = mCurrentTexture;
862*38e8c45fSAndroid Build Coastguard Worker     }
863*38e8c45fSAndroid Build Coastguard Worker 
864*38e8c45fSAndroid Build Coastguard Worker     return (mCurrentTextureImage == nullptr) ?
865*38e8c45fSAndroid Build Coastguard Worker             nullptr : mCurrentTextureImage->graphicBuffer();
866*38e8c45fSAndroid Build Coastguard Worker }
867*38e8c45fSAndroid Build Coastguard Worker 
getCurrentCrop() const868*38e8c45fSAndroid Build Coastguard Worker Rect GLConsumer::getCurrentCrop() const {
869*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
870*38e8c45fSAndroid Build Coastguard Worker     return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
871*38e8c45fSAndroid Build Coastguard Worker         ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
872*38e8c45fSAndroid Build Coastguard Worker         : mCurrentCrop;
873*38e8c45fSAndroid Build Coastguard Worker }
874*38e8c45fSAndroid Build Coastguard Worker 
getCurrentTransform() const875*38e8c45fSAndroid Build Coastguard Worker uint32_t GLConsumer::getCurrentTransform() const {
876*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
877*38e8c45fSAndroid Build Coastguard Worker     return mCurrentTransform;
878*38e8c45fSAndroid Build Coastguard Worker }
879*38e8c45fSAndroid Build Coastguard Worker 
getCurrentScalingMode() const880*38e8c45fSAndroid Build Coastguard Worker uint32_t GLConsumer::getCurrentScalingMode() const {
881*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
882*38e8c45fSAndroid Build Coastguard Worker     return mCurrentScalingMode;
883*38e8c45fSAndroid Build Coastguard Worker }
884*38e8c45fSAndroid Build Coastguard Worker 
getCurrentFence() const885*38e8c45fSAndroid Build Coastguard Worker sp<Fence> GLConsumer::getCurrentFence() const {
886*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
887*38e8c45fSAndroid Build Coastguard Worker     return mCurrentFence;
888*38e8c45fSAndroid Build Coastguard Worker }
889*38e8c45fSAndroid Build Coastguard Worker 
getCurrentFenceTime() const890*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
891*38e8c45fSAndroid Build Coastguard Worker     Mutex::Autolock lock(mMutex);
892*38e8c45fSAndroid Build Coastguard Worker     return mCurrentFenceTime;
893*38e8c45fSAndroid Build Coastguard Worker }
894*38e8c45fSAndroid Build Coastguard Worker 
doGLFenceWaitLocked() const895*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::doGLFenceWaitLocked() const {
896*38e8c45fSAndroid Build Coastguard Worker 
897*38e8c45fSAndroid Build Coastguard Worker     EGLDisplay dpy = eglGetCurrentDisplay();
898*38e8c45fSAndroid Build Coastguard Worker     EGLContext ctx = eglGetCurrentContext();
899*38e8c45fSAndroid Build Coastguard Worker 
900*38e8c45fSAndroid Build Coastguard Worker     if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
901*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
902*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
903*38e8c45fSAndroid Build Coastguard Worker     }
904*38e8c45fSAndroid Build Coastguard Worker 
905*38e8c45fSAndroid Build Coastguard Worker     if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
906*38e8c45fSAndroid Build Coastguard Worker         GLC_LOGE("doGLFenceWait: invalid current EGLContext");
907*38e8c45fSAndroid Build Coastguard Worker         return INVALID_OPERATION;
908*38e8c45fSAndroid Build Coastguard Worker     }
909*38e8c45fSAndroid Build Coastguard Worker 
910*38e8c45fSAndroid Build Coastguard Worker     if (mCurrentFence->isValid()) {
911*38e8c45fSAndroid Build Coastguard Worker         if (SyncFeatures::getInstance().useWaitSync() &&
912*38e8c45fSAndroid Build Coastguard Worker             SyncFeatures::getInstance().useNativeFenceSync()) {
913*38e8c45fSAndroid Build Coastguard Worker             // Create an EGLSyncKHR from the current fence.
914*38e8c45fSAndroid Build Coastguard Worker             int fenceFd = mCurrentFence->dup();
915*38e8c45fSAndroid Build Coastguard Worker             if (fenceFd == -1) {
916*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
917*38e8c45fSAndroid Build Coastguard Worker                 return -errno;
918*38e8c45fSAndroid Build Coastguard Worker             }
919*38e8c45fSAndroid Build Coastguard Worker             EGLint attribs[] = {
920*38e8c45fSAndroid Build Coastguard Worker                 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
921*38e8c45fSAndroid Build Coastguard Worker                 EGL_NONE
922*38e8c45fSAndroid Build Coastguard Worker             };
923*38e8c45fSAndroid Build Coastguard Worker             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
924*38e8c45fSAndroid Build Coastguard Worker                     EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
925*38e8c45fSAndroid Build Coastguard Worker             if (sync == EGL_NO_SYNC_KHR) {
926*38e8c45fSAndroid Build Coastguard Worker                 close(fenceFd);
927*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
928*38e8c45fSAndroid Build Coastguard Worker                         eglGetError());
929*38e8c45fSAndroid Build Coastguard Worker                 return UNKNOWN_ERROR;
930*38e8c45fSAndroid Build Coastguard Worker             }
931*38e8c45fSAndroid Build Coastguard Worker 
932*38e8c45fSAndroid Build Coastguard Worker             // XXX: The spec draft is inconsistent as to whether this should
933*38e8c45fSAndroid Build Coastguard Worker             // return an EGLint or void.  Ignore the return value for now, as
934*38e8c45fSAndroid Build Coastguard Worker             // it's not strictly needed.
935*38e8c45fSAndroid Build Coastguard Worker             eglWaitSyncKHR(dpy, sync, 0);
936*38e8c45fSAndroid Build Coastguard Worker             EGLint eglErr = eglGetError();
937*38e8c45fSAndroid Build Coastguard Worker             eglDestroySyncKHR(dpy, sync);
938*38e8c45fSAndroid Build Coastguard Worker             if (eglErr != EGL_SUCCESS) {
939*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
940*38e8c45fSAndroid Build Coastguard Worker                         eglErr);
941*38e8c45fSAndroid Build Coastguard Worker                 return UNKNOWN_ERROR;
942*38e8c45fSAndroid Build Coastguard Worker             }
943*38e8c45fSAndroid Build Coastguard Worker         } else {
944*38e8c45fSAndroid Build Coastguard Worker             status_t err = mCurrentFence->waitForever(
945*38e8c45fSAndroid Build Coastguard Worker                     "GLConsumer::doGLFenceWaitLocked");
946*38e8c45fSAndroid Build Coastguard Worker             if (err != NO_ERROR) {
947*38e8c45fSAndroid Build Coastguard Worker                 GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
948*38e8c45fSAndroid Build Coastguard Worker                 return err;
949*38e8c45fSAndroid Build Coastguard Worker             }
950*38e8c45fSAndroid Build Coastguard Worker         }
951*38e8c45fSAndroid Build Coastguard Worker     }
952*38e8c45fSAndroid Build Coastguard Worker 
953*38e8c45fSAndroid Build Coastguard Worker     return NO_ERROR;
954*38e8c45fSAndroid Build Coastguard Worker }
955*38e8c45fSAndroid Build Coastguard Worker 
freeBufferLocked(int slotIndex)956*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::freeBufferLocked(int slotIndex) {
957*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
958*38e8c45fSAndroid Build Coastguard Worker     if (slotIndex == mCurrentTexture) {
959*38e8c45fSAndroid Build Coastguard Worker         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
960*38e8c45fSAndroid Build Coastguard Worker     }
961*38e8c45fSAndroid Build Coastguard Worker     mEglSlots[slotIndex].mEglImage.clear();
962*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::freeBufferLocked(slotIndex);
963*38e8c45fSAndroid Build Coastguard Worker }
964*38e8c45fSAndroid Build Coastguard Worker 
abandonLocked()965*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::abandonLocked() {
966*38e8c45fSAndroid Build Coastguard Worker     GLC_LOGV("abandonLocked");
967*38e8c45fSAndroid Build Coastguard Worker     mCurrentTextureImage.clear();
968*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::abandonLocked();
969*38e8c45fSAndroid Build Coastguard Worker }
970*38e8c45fSAndroid Build Coastguard Worker 
setConsumerUsageBits(uint64_t usage)971*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
972*38e8c45fSAndroid Build Coastguard Worker     return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
973*38e8c45fSAndroid Build Coastguard Worker }
974*38e8c45fSAndroid Build Coastguard Worker 
dumpLocked(String8 & result,const char * prefix) const975*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::dumpLocked(String8& result, const char* prefix) const
976*38e8c45fSAndroid Build Coastguard Worker {
977*38e8c45fSAndroid Build Coastguard Worker     result.appendFormat(
978*38e8c45fSAndroid Build Coastguard Worker        "%smTexName=%d mCurrentTexture=%d\n"
979*38e8c45fSAndroid Build Coastguard Worker        "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
980*38e8c45fSAndroid Build Coastguard Worker        prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
981*38e8c45fSAndroid Build Coastguard Worker        mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
982*38e8c45fSAndroid Build Coastguard Worker        mCurrentTransform);
983*38e8c45fSAndroid Build Coastguard Worker 
984*38e8c45fSAndroid Build Coastguard Worker     ConsumerBase::dumpLocked(result, prefix);
985*38e8c45fSAndroid Build Coastguard Worker }
986*38e8c45fSAndroid Build Coastguard Worker 
EglImage(sp<GraphicBuffer> graphicBuffer)987*38e8c45fSAndroid Build Coastguard Worker GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
988*38e8c45fSAndroid Build Coastguard Worker     mGraphicBuffer(graphicBuffer),
989*38e8c45fSAndroid Build Coastguard Worker     mEglImage(EGL_NO_IMAGE_KHR),
990*38e8c45fSAndroid Build Coastguard Worker     mEglDisplay(EGL_NO_DISPLAY) {
991*38e8c45fSAndroid Build Coastguard Worker }
992*38e8c45fSAndroid Build Coastguard Worker 
~EglImage()993*38e8c45fSAndroid Build Coastguard Worker GLConsumer::EglImage::~EglImage() {
994*38e8c45fSAndroid Build Coastguard Worker     if (mEglImage != EGL_NO_IMAGE_KHR) {
995*38e8c45fSAndroid Build Coastguard Worker         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
996*38e8c45fSAndroid Build Coastguard Worker            ALOGE("~EglImage: eglDestroyImageKHR failed");
997*38e8c45fSAndroid Build Coastguard Worker         }
998*38e8c45fSAndroid Build Coastguard Worker         DEBUG_EGL_IMAGE_TRACKER_DESTROY();
999*38e8c45fSAndroid Build Coastguard Worker         eglTerminate(mEglDisplay);
1000*38e8c45fSAndroid Build Coastguard Worker     }
1001*38e8c45fSAndroid Build Coastguard Worker }
1002*38e8c45fSAndroid Build Coastguard Worker 
createIfNeeded(EGLDisplay eglDisplay,bool forceCreation)1003*38e8c45fSAndroid Build Coastguard Worker status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
1004*38e8c45fSAndroid Build Coastguard Worker                                               bool forceCreation) {
1005*38e8c45fSAndroid Build Coastguard Worker     // If there's an image and it's no longer valid, destroy it.
1006*38e8c45fSAndroid Build Coastguard Worker     bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
1007*38e8c45fSAndroid Build Coastguard Worker     bool displayInvalid = mEglDisplay != eglDisplay;
1008*38e8c45fSAndroid Build Coastguard Worker     if (haveImage && (displayInvalid || forceCreation)) {
1009*38e8c45fSAndroid Build Coastguard Worker         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1010*38e8c45fSAndroid Build Coastguard Worker            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
1011*38e8c45fSAndroid Build Coastguard Worker         }
1012*38e8c45fSAndroid Build Coastguard Worker         DEBUG_EGL_IMAGE_TRACKER_DESTROY();
1013*38e8c45fSAndroid Build Coastguard Worker         eglTerminate(mEglDisplay);
1014*38e8c45fSAndroid Build Coastguard Worker         mEglImage = EGL_NO_IMAGE_KHR;
1015*38e8c45fSAndroid Build Coastguard Worker         mEglDisplay = EGL_NO_DISPLAY;
1016*38e8c45fSAndroid Build Coastguard Worker     }
1017*38e8c45fSAndroid Build Coastguard Worker 
1018*38e8c45fSAndroid Build Coastguard Worker     // If there's no image, create one.
1019*38e8c45fSAndroid Build Coastguard Worker     if (mEglImage == EGL_NO_IMAGE_KHR) {
1020*38e8c45fSAndroid Build Coastguard Worker         mEglDisplay = eglDisplay;
1021*38e8c45fSAndroid Build Coastguard Worker         mEglImage = createImage(mEglDisplay, mGraphicBuffer);
1022*38e8c45fSAndroid Build Coastguard Worker     }
1023*38e8c45fSAndroid Build Coastguard Worker 
1024*38e8c45fSAndroid Build Coastguard Worker     // Fail if we can't create a valid image.
1025*38e8c45fSAndroid Build Coastguard Worker     if (mEglImage == EGL_NO_IMAGE_KHR) {
1026*38e8c45fSAndroid Build Coastguard Worker         mEglDisplay = EGL_NO_DISPLAY;
1027*38e8c45fSAndroid Build Coastguard Worker         const sp<GraphicBuffer>& buffer = mGraphicBuffer;
1028*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
1029*38e8c45fSAndroid Build Coastguard Worker             buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
1030*38e8c45fSAndroid Build Coastguard Worker             buffer->getUsage(), buffer->getPixelFormat());
1031*38e8c45fSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1032*38e8c45fSAndroid Build Coastguard Worker     }
1033*38e8c45fSAndroid Build Coastguard Worker 
1034*38e8c45fSAndroid Build Coastguard Worker     return OK;
1035*38e8c45fSAndroid Build Coastguard Worker }
1036*38e8c45fSAndroid Build Coastguard Worker 
bindToTextureTarget(uint32_t texTarget)1037*38e8c45fSAndroid Build Coastguard Worker void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1038*38e8c45fSAndroid Build Coastguard Worker     glEGLImageTargetTexture2DOES(texTarget,
1039*38e8c45fSAndroid Build Coastguard Worker             static_cast<GLeglImageOES>(mEglImage));
1040*38e8c45fSAndroid Build Coastguard Worker }
1041*38e8c45fSAndroid Build Coastguard Worker 
createImage(EGLDisplay dpy,const sp<GraphicBuffer> & graphicBuffer)1042*38e8c45fSAndroid Build Coastguard Worker EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
1043*38e8c45fSAndroid Build Coastguard Worker         const sp<GraphicBuffer>& graphicBuffer) {
1044*38e8c45fSAndroid Build Coastguard Worker     EGLClientBuffer cbuf =
1045*38e8c45fSAndroid Build Coastguard Worker             static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1046*38e8c45fSAndroid Build Coastguard Worker     const bool createProtectedImage =
1047*38e8c45fSAndroid Build Coastguard Worker             (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
1048*38e8c45fSAndroid Build Coastguard Worker             hasEglProtectedContent();
1049*38e8c45fSAndroid Build Coastguard Worker     EGLint attrs[] = {
1050*38e8c45fSAndroid Build Coastguard Worker         EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
1051*38e8c45fSAndroid Build Coastguard Worker         createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1052*38e8c45fSAndroid Build Coastguard Worker         createProtectedImage ? EGL_TRUE : EGL_NONE,
1053*38e8c45fSAndroid Build Coastguard Worker         EGL_NONE,
1054*38e8c45fSAndroid Build Coastguard Worker     };
1055*38e8c45fSAndroid Build Coastguard Worker     eglInitialize(dpy, nullptr, nullptr);
1056*38e8c45fSAndroid Build Coastguard Worker     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
1057*38e8c45fSAndroid Build Coastguard Worker             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
1058*38e8c45fSAndroid Build Coastguard Worker     if (image == EGL_NO_IMAGE_KHR) {
1059*38e8c45fSAndroid Build Coastguard Worker         EGLint error = eglGetError();
1060*38e8c45fSAndroid Build Coastguard Worker         ALOGE("error creating EGLImage: %#x", error);
1061*38e8c45fSAndroid Build Coastguard Worker         eglTerminate(dpy);
1062*38e8c45fSAndroid Build Coastguard Worker     } else {
1063*38e8c45fSAndroid Build Coastguard Worker         DEBUG_EGL_IMAGE_TRACKER_CREATE();
1064*38e8c45fSAndroid Build Coastguard Worker     }
1065*38e8c45fSAndroid Build Coastguard Worker 
1066*38e8c45fSAndroid Build Coastguard Worker     return image;
1067*38e8c45fSAndroid Build Coastguard Worker }
1068*38e8c45fSAndroid Build Coastguard Worker 
1069*38e8c45fSAndroid Build Coastguard Worker }; // namespace android
1070