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