blob: 8199c9858270d93909e2a11e5d0becf24b98b4a5 [file] [log] [blame]
Jamie Gennis8ba32fa2010-12-20 11:27:26 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andy McFadden2adaf042012-12-18 09:49:45 -080017#define LOG_TAG "GLConsumer"
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080018#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Jamie Gennise70d8b42011-01-09 13:24:09 -080019//#define LOG_NDEBUG 0
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080020
21#define GL_GLEXT_PROTOTYPES
22#define EGL_EGLEXT_PROTOTYPES
23
Mathias Agopiancb496ac2017-05-22 14:21:00 -070024#include <inttypes.h>
25
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080026#include <EGL/egl.h>
27#include <EGL/eglext.h>
28#include <GLES2/gl2.h>
29#include <GLES2/gl2ext.h>
Mathias Agopianad678e12013-07-23 17:28:53 -070030#include <cutils/compiler.h>
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080031
Jamie Gennis9fea3422012-08-07 18:03:04 -070032#include <hardware/hardware.h>
33
Chia-I Wu3bd03ff2017-11-17 12:04:57 -080034#include <math/mat4.h>
35
Dan Stozadd264162015-03-12 13:58:47 -070036#include <gui/BufferItem.h>
Ady Abrahama3b08ef2019-07-15 18:43:10 -070037#include <gui/DebugEGLImageTracker.h>
Mathias Agopianca088332013-03-28 17:44:13 -070038#include <gui/GLConsumer.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080039#include <gui/ISurfaceComposer.h>
40#include <gui/SurfaceComposerClient.h>
Mathias Agopian41f673c2011-11-17 17:48:35 -080041
Mathias Agopian90ac7992012-02-25 18:48:35 -080042#include <private/gui/ComposerService.h>
Mathias Agopianca088332013-03-28 17:44:13 -070043#include <private/gui/SyncFeatures.h>
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080044
45#include <utils/Log.h>
Mathias Agopian68c77942011-05-09 19:08:33 -070046#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080047#include <utils/Trace.h>
Jamie Gennis8ba32fa2010-12-20 11:27:26 -080048
Jiyong Park00b15b82017-08-10 20:30:56 +090049extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
Craig Donneraec86972016-04-28 18:09:40 -070050#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
51#define EGL_PROTECTED_CONTENT_EXT 0x32C0
Jamie Gennisdbe92452013-09-23 17:22:10 -070052
Andy McFadden97eba892012-12-11 15:21:45 -080053namespace android {
54
Andy McFadden2adaf042012-12-18 09:49:45 -080055// Macros for including the GLConsumer name in log messages
Dan Stozad723bd72014-11-18 10:24:03 -080056#define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
57#define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
58//#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
59#define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
60#define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
Mathias Agopian29b57622011-08-17 15:42:04 -070061
Mathias Agopianad678e12013-07-23 17:28:53 -070062static const struct {
Dan Stozad723bd72014-11-18 10:24:03 -080063 uint32_t width, height;
Mathias Agopianad678e12013-07-23 17:28:53 -070064 char const* bits;
Mathias Agopian45263e22013-08-07 13:35:20 -070065} kDebugData = { 15, 12,
Dan Stozad723bd72014-11-18 10:24:03 -080066 "_______________"
67 "_______________"
68 "_____XX_XX_____"
69 "__X_X_____X_X__"
70 "__X_XXXXXXX_X__"
71 "__XXXXXXXXXXX__"
72 "___XX_XXX_XX___"
73 "____XXXXXXX____"
74 "_____X___X_____"
75 "____X_____X____"
76 "_______________"
77 "_______________"
Mathias Agopian45263e22013-08-07 13:35:20 -070078};
Mathias Agopianad678e12013-07-23 17:28:53 -070079
Chia-I Wu3bd03ff2017-11-17 12:04:57 -080080static const mat4 mtxIdentity;
Jamie Gennisf238e282011-01-09 16:33:17 -080081
Mathias Agopian9870c9b2013-08-08 17:46:48 -070082Mutex GLConsumer::sStaticInitLock;
83sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
Jamie Gennisfa28c352011-09-16 17:30:26 -070084
Craig Donneraec86972016-04-28 18:09:40 -070085static bool hasEglProtectedContentImpl() {
86 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
87 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
88 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
89 size_t extsLen = strlen(exts);
90 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
91 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
92 bool atEnd = (cropExtLen+1) < extsLen &&
93 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
94 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
Craig Donner4df76b22016-06-13 22:14:15 +000095 return equal || atStart || atEnd || inMiddle;
Craig Donneraec86972016-04-28 18:09:40 -070096}
97
98static bool hasEglProtectedContent() {
99 // Only compute whether the extension is present once the first time this
100 // function is called.
101 static bool hasIt = hasEglProtectedContentImpl();
102 return hasIt;
103}
104
Mathias Agopian3f844832013-08-07 21:24:32 -0700105GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
106 uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
Mathias Agopian595264f2013-07-16 22:56:09 -0700107 ConsumerBase(bq, isControlledByApp),
Pablo Ceballos60d69222015-08-07 14:47:20 -0700108 mCurrentCrop(Rect::EMPTY_RECT),
Eino-Ville Talvala1d01a122011-02-18 11:02:42 -0800109 mCurrentTransform(0),
Mathias Agopiane692ab92013-04-22 11:24:02 +0200110 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
Jamie Gennis1df8c342012-12-20 14:05:45 -0800111 mCurrentFence(Fence::NO_FENCE),
Eino-Ville Talvala1d01a122011-02-18 11:02:42 -0800112 mCurrentTimestamp(0),
Courtney Goeltzenleuchterbb09b432016-11-30 13:51:28 -0700113 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
Eino-Ville Talvalad171da92013-09-19 13:36:07 -0700114 mCurrentFrameNumber(0),
Mathias Agopiane692ab92013-04-22 11:24:02 +0200115 mDefaultWidth(1),
116 mDefaultHeight(1),
Jamie Gennis5c1139f2012-05-08 16:56:34 -0700117 mFilteringEnabled(true),
Mathias Agopianb3e518c2011-04-21 18:52:51 -0700118 mTexName(tex),
Jamie Gennis86edf4f2011-11-14 14:51:01 -0800119 mUseFenceSync(useFenceSync),
Daniel Lameae59d22012-01-22 15:26:27 -0800120 mTexTarget(texTarget),
Jamie Gennisce561372012-03-19 18:33:05 -0700121 mEglDisplay(EGL_NO_DISPLAY),
122 mEglContext(EGL_NO_CONTEXT),
Jamie Gennis74bed552012-03-28 19:05:54 -0700123 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
124 mAttached(true)
Daniel Lam6b091c52012-01-22 15:26:27 -0800125{
Dan Stozad723bd72014-11-18 10:24:03 -0800126 GLC_LOGV("GLConsumer");
Daniel Lamb2675792012-02-23 14:35:13 -0800127
Chia-I Wu3bd03ff2017-11-17 12:04:57 -0800128 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
Jamie Gennisfa28c352011-09-16 17:30:26 -0700129 sizeof(mCurrentTransformMatrix));
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700130
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700131 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800132}
133
Dan Stozaab574912014-06-25 14:21:45 -0700134GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
135 bool useFenceSync, bool isControlledByApp) :
136 ConsumerBase(bq, isControlledByApp),
Pablo Ceballos60d69222015-08-07 14:47:20 -0700137 mCurrentCrop(Rect::EMPTY_RECT),
Dan Stozaab574912014-06-25 14:21:45 -0700138 mCurrentTransform(0),
139 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
140 mCurrentFence(Fence::NO_FENCE),
141 mCurrentTimestamp(0),
Courtney Goeltzenleuchterbb09b432016-11-30 13:51:28 -0700142 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
Dan Stozaab574912014-06-25 14:21:45 -0700143 mCurrentFrameNumber(0),
144 mDefaultWidth(1),
145 mDefaultHeight(1),
146 mFilteringEnabled(true),
Dan Stozad723bd72014-11-18 10:24:03 -0800147 mTexName(0),
Dan Stozaab574912014-06-25 14:21:45 -0700148 mUseFenceSync(useFenceSync),
149 mTexTarget(texTarget),
150 mEglDisplay(EGL_NO_DISPLAY),
151 mEglContext(EGL_NO_CONTEXT),
152 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
153 mAttached(false)
154{
Dan Stozad723bd72014-11-18 10:24:03 -0800155 GLC_LOGV("GLConsumer");
Dan Stozaab574912014-06-25 14:21:45 -0700156
Chia-I Wu3bd03ff2017-11-17 12:04:57 -0800157 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
Dan Stozaab574912014-06-25 14:21:45 -0700158 sizeof(mCurrentTransformMatrix));
159
160 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
161}
162
Andy McFadden2adaf042012-12-18 09:49:45 -0800163status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
Mathias Agopiana5c75c02011-03-31 19:10:24 -0700164{
Daniel Lamb2675792012-02-23 14:35:13 -0800165 Mutex::Autolock lock(mMutex);
Pablo Ceballos65d9f6d2016-05-04 13:59:35 -0700166 if (mAbandoned) {
167 GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
168 return NO_INIT;
169 }
Daniel Lam016c8cb2012-04-03 15:54:58 -0700170 mDefaultWidth = w;
171 mDefaultHeight = h;
Mathias Agopiandb89edc2013-08-02 01:40:18 -0700172 return mConsumer->setDefaultBufferSize(w, h);
Mathias Agopiana5c75c02011-03-31 19:10:24 -0700173}
174
Andy McFadden2adaf042012-12-18 09:49:45 -0800175status_t GLConsumer::updateTexImage() {
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800176 ATRACE_CALL();
Dan Stozad723bd72014-11-18 10:24:03 -0800177 GLC_LOGV("updateTexImage");
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800178 Mutex::Autolock lock(mMutex);
179
180 if (mAbandoned) {
Dan Stozad723bd72014-11-18 10:24:03 -0800181 GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800182 return NO_INIT;
183 }
184
185 // Make sure the EGL state is the same as in previous calls.
186 status_t err = checkAndUpdateEglStateLocked();
187 if (err != NO_ERROR) {
188 return err;
189 }
190
Dan Stozadd264162015-03-12 13:58:47 -0700191 BufferItem item;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800192
193 // Acquire the next buffer.
194 // In asynchronous mode the list is guaranteed to be one buffer
195 // deep, while in synchronous mode we use the oldest buffer.
Andy McFadden1585c4d2013-06-28 13:52:40 -0700196 err = acquireBufferLocked(&item, 0);
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800197 if (err != NO_ERROR) {
198 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
199 // We always bind the texture even if we don't update its contents.
Dan Stozad723bd72014-11-18 10:24:03 -0800200 GLC_LOGV("updateTexImage: no buffers were available");
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800201 glBindTexture(mTexTarget, mTexName);
202 err = NO_ERROR;
203 } else {
Dan Stozad723bd72014-11-18 10:24:03 -0800204 GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800205 strerror(-err), err);
206 }
207 return err;
208 }
209
210 // Release the previous buffer.
Mathias Agopianad678e12013-07-23 17:28:53 -0700211 err = updateAndReleaseLocked(item);
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800212 if (err != NO_ERROR) {
213 // We always bind the texture.
214 glBindTexture(mTexTarget, mTexName);
215 return err;
216 }
217
Andy McFadden97eba892012-12-11 15:21:45 -0800218 // Bind the new buffer to the GL texture, and wait until it's ready.
219 return bindTextureImageLocked();
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700220}
221
Mathias Agopianad678e12013-07-23 17:28:53 -0700222
223status_t GLConsumer::releaseTexImage() {
224 ATRACE_CALL();
Dan Stozad723bd72014-11-18 10:24:03 -0800225 GLC_LOGV("releaseTexImage");
Mathias Agopianad678e12013-07-23 17:28:53 -0700226 Mutex::Autolock lock(mMutex);
227
228 if (mAbandoned) {
Dan Stozad723bd72014-11-18 10:24:03 -0800229 GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
Mathias Agopianad678e12013-07-23 17:28:53 -0700230 return NO_INIT;
231 }
232
233 // Make sure the EGL state is the same as in previous calls.
Mathias Agopian45155962013-08-08 18:16:21 -0700234 status_t err = NO_ERROR;
235
236 if (mAttached) {
237 err = checkAndUpdateEglStateLocked(true);
238 if (err != NO_ERROR) {
239 return err;
240 }
241 } else {
242 // if we're detached, no need to validate EGL's state -- we won't use it.
Mathias Agopianad678e12013-07-23 17:28:53 -0700243 }
244
245 // Update the GLConsumer state.
246 int buf = mCurrentTexture;
247 if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
248
Dan Stozad723bd72014-11-18 10:24:03 -0800249 GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
Mathias Agopianad678e12013-07-23 17:28:53 -0700250
Mathias Agopian45155962013-08-08 18:16:21 -0700251 if (mAttached) {
252 // Do whatever sync ops we need to do before releasing the slot.
253 err = syncForReleaseLocked(mEglDisplay);
254 if (err != NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800255 GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
Mathias Agopian45155962013-08-08 18:16:21 -0700256 return err;
257 }
258 } else {
259 // if we're detached, we just use the fence that was created in detachFromContext()
260 // so... basically, nothing more to do here.
Mathias Agopianad678e12013-07-23 17:28:53 -0700261 }
262
Mathias Agopian45155962013-08-08 18:16:21 -0700263 err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
Mathias Agopianad678e12013-07-23 17:28:53 -0700264 if (err < NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800265 GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
Mathias Agopianad678e12013-07-23 17:28:53 -0700266 strerror(-err), err);
267 return err;
268 }
269
Yi Kong48a619f2018-06-05 16:34:59 -0700270 if (mReleasedTexImage == nullptr) {
Eric Penner5c3d2432014-07-11 19:08:04 -0700271 mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
272 }
273
Mathias Agopianad678e12013-07-23 17:28:53 -0700274 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
Eric Penner5c3d2432014-07-11 19:08:04 -0700275 mCurrentTextureImage = mReleasedTexImage;
Mathias Agopianad678e12013-07-23 17:28:53 -0700276 mCurrentCrop.makeInvalid();
277 mCurrentTransform = 0;
Mathias Agopianad678e12013-07-23 17:28:53 -0700278 mCurrentTimestamp = 0;
Courtney Goeltzenleuchterbb09b432016-11-30 13:51:28 -0700279 mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopianad678e12013-07-23 17:28:53 -0700280 mCurrentFence = Fence::NO_FENCE;
Brian Anderson3d4039d2016-09-23 16:31:30 -0700281 mCurrentFenceTime = FenceTime::NO_FENCE;
Mathias Agopianad678e12013-07-23 17:28:53 -0700282
Mathias Agopian45155962013-08-08 18:16:21 -0700283 if (mAttached) {
Eric Penner5c3d2432014-07-11 19:08:04 -0700284 // This binds a dummy buffer (mReleasedTexImage).
Dan Stozad723bd72014-11-18 10:24:03 -0800285 status_t result = bindTextureImageLocked();
286 if (result != NO_ERROR) {
287 return result;
Eric Penner5c3d2432014-07-11 19:08:04 -0700288 }
Mathias Agopian45155962013-08-08 18:16:21 -0700289 } else {
290 // detached, don't touch the texture (and we may not even have an
291 // EGLDisplay here.
292 }
Mathias Agopianad678e12013-07-23 17:28:53 -0700293 }
294
295 return NO_ERROR;
296}
297
Mathias Agopian9870c9b2013-08-08 17:46:48 -0700298sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
299 Mutex::Autolock _l(sStaticInitLock);
Yi Kong48a619f2018-06-05 16:34:59 -0700300 if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
Mathias Agopian9870c9b2013-08-08 17:46:48 -0700301 // The first time, create the debug texture in case the application
302 // continues to use it.
303 sp<GraphicBuffer> buffer = new GraphicBuffer(
304 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
Dan Stozad4079af2016-08-22 17:26:41 -0700305 GraphicBuffer::USAGE_SW_WRITE_RARELY,
306 "[GLConsumer debug texture]");
Mathias Agopian9870c9b2013-08-08 17:46:48 -0700307 uint32_t* bits;
308 buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
Dan Stozad723bd72014-11-18 10:24:03 -0800309 uint32_t stride = buffer->getStride();
310 uint32_t height = buffer->getHeight();
311 memset(bits, 0, stride * height * 4);
312 for (uint32_t y = 0; y < kDebugData.height; y++) {
313 for (uint32_t x = 0; x < kDebugData.width; x++) {
314 bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
315 0xFF000000 : 0xFFFFFFFF;
Mathias Agopian9870c9b2013-08-08 17:46:48 -0700316 }
Dan Stozad723bd72014-11-18 10:24:03 -0800317 bits += stride;
Mathias Agopian9870c9b2013-08-08 17:46:48 -0700318 }
319 buffer->unlock();
320 sReleasedTexImageBuffer = buffer;
321 }
322 return sReleasedTexImageBuffer;
323}
324
Dan Stozadd264162015-03-12 13:58:47 -0700325status_t GLConsumer::acquireBufferLocked(BufferItem *item,
Dan Stozaa4650a52015-05-12 12:56:16 -0700326 nsecs_t presentWhen, uint64_t maxFrameNumber) {
327 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
328 maxFrameNumber);
Jamie Gennis9fea3422012-08-07 18:03:04 -0700329 if (err != NO_ERROR) {
330 return err;
331 }
332
Eric Penner5c3d2432014-07-11 19:08:04 -0700333 // If item->mGraphicBuffer is not null, this buffer has not been acquired
334 // before, so any prior EglImage created is using a stale buffer. This
335 // replaces any old EglImage with a new one (using the new buffer).
Yi Kong48a619f2018-06-05 16:34:59 -0700336 if (item->mGraphicBuffer != nullptr) {
Pablo Ceballos47650f42015-08-04 16:38:17 -0700337 int slot = item->mSlot;
Eric Penner5c3d2432014-07-11 19:08:04 -0700338 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
Jamie Gennisdbe92452013-09-23 17:22:10 -0700339 }
340
Jamie Gennis9fea3422012-08-07 18:03:04 -0700341 return NO_ERROR;
342}
343
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700344status_t GLConsumer::releaseBufferLocked(int buf,
345 sp<GraphicBuffer> graphicBuffer,
346 EGLDisplay display, EGLSyncKHR eglFence) {
347 // release the buffer if it hasn't already been discarded by the
348 // BufferQueue. This can happen, for example, when the producer of this
349 // buffer has reallocated the original buffer slot after this buffer
350 // was acquired.
351 status_t err = ConsumerBase::releaseBufferLocked(
352 buf, graphicBuffer, display, eglFence);
Jamie Gennisd1b330d2012-09-21 11:55:35 -0700353 mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
Jamie Gennis9fea3422012-08-07 18:03:04 -0700354 return err;
355}
356
Dan Stoza3ce46042015-11-17 17:00:45 -0800357status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
358 PendingRelease* pendingRelease)
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800359{
Daniel Lam9abe1eb2012-03-26 20:37:15 -0700360 status_t err = NO_ERROR;
361
Pablo Ceballos47650f42015-08-04 16:38:17 -0700362 int slot = item.mSlot;
Andy McFadden87a67842014-04-04 15:37:08 -0700363
Jamie Gennis74bed552012-03-28 19:05:54 -0700364 if (!mAttached) {
Dan Stozad723bd72014-11-18 10:24:03 -0800365 GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
Jamie Gennis74bed552012-03-28 19:05:54 -0700366 "ES context");
Pablo Ceballos47650f42015-08-04 16:38:17 -0700367 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
Andy McFadden87a67842014-04-04 15:37:08 -0700368 mEglDisplay, EGL_NO_SYNC_KHR);
Jamie Gennis74bed552012-03-28 19:05:54 -0700369 return INVALID_OPERATION;
370 }
371
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800372 // Confirm state.
373 err = checkAndUpdateEglStateLocked();
374 if (err != NO_ERROR) {
Pablo Ceballos47650f42015-08-04 16:38:17 -0700375 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
Andy McFadden87a67842014-04-04 15:37:08 -0700376 mEglDisplay, EGL_NO_SYNC_KHR);
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800377 return err;
378 }
379
Eric Penner5c3d2432014-07-11 19:08:04 -0700380 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
381 // if nessessary, for the gralloc buffer currently in the slot in
382 // ConsumerBase.
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800383 // We may have to do this even when item.mGraphicBuffer == NULL (which
Eric Penner5c3d2432014-07-11 19:08:04 -0700384 // means the buffer was previously acquired).
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700385 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay);
Eric Penner5c3d2432014-07-11 19:08:04 -0700386 if (err != NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800387 GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
Pablo Ceballos47650f42015-08-04 16:38:17 -0700388 mEglDisplay, slot);
389 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
Eric Penner5c3d2432014-07-11 19:08:04 -0700390 mEglDisplay, EGL_NO_SYNC_KHR);
391 return UNKNOWN_ERROR;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800392 }
393
394 // Do whatever sync ops we need to do before releasing the old slot.
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800395 if (slot != mCurrentTexture) {
Pablo Ceballos33fcc2e2015-11-20 15:44:51 -0800396 err = syncForReleaseLocked(mEglDisplay);
397 if (err != NO_ERROR) {
398 // Release the buffer we just acquired. It's not safe to
399 // release the old buffer, so instead we just drop the new frame.
400 // As we are still under lock since acquireBuffer, it is safe to
401 // release by slot.
402 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
403 mEglDisplay, EGL_NO_SYNC_KHR);
404 return err;
405 }
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800406 }
407
Dan Stozad723bd72014-11-18 10:24:03 -0800408 GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
Yi Konga03e0442018-07-17 11:16:57 -0700409 mCurrentTexture, mCurrentTextureImage != nullptr ?
Yi Kong48a619f2018-06-05 16:34:59 -0700410 mCurrentTextureImage->graphicBufferHandle() : nullptr,
Pablo Ceballos47650f42015-08-04 16:38:17 -0700411 slot, mSlots[slot].mGraphicBuffer->handle);
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800412
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700413 // Hang onto the pointer so that it isn't freed in the call to
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700414 // releaseBufferLocked() if we're in shared buffer mode and both buffers are
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700415 // the same.
416 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
417
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800418 // release old buffer
419 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
Dan Stoza3ce46042015-11-17 17:00:45 -0800420 if (pendingRelease == nullptr) {
421 status_t status = releaseBufferLocked(
422 mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
423 mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
424 if (status < NO_ERROR) {
425 GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
426 strerror(-status), status);
427 err = status;
428 // keep going, with error raised [?]
429 }
430 } else {
431 pendingRelease->currentTexture = mCurrentTexture;
432 pendingRelease->graphicBuffer =
433 mCurrentTextureImage->graphicBuffer();
434 pendingRelease->display = mEglDisplay;
435 pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
436 pendingRelease->isPending = true;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800437 }
438 }
439
Andy McFadden2adaf042012-12-18 09:49:45 -0800440 // Update the GLConsumer state.
Pablo Ceballos47650f42015-08-04 16:38:17 -0700441 mCurrentTexture = slot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700442 mCurrentTextureImage = nextTextureImage;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800443 mCurrentCrop = item.mCrop;
444 mCurrentTransform = item.mTransform;
445 mCurrentScalingMode = item.mScalingMode;
446 mCurrentTimestamp = item.mTimestamp;
Courtney Goeltzenleuchterbb09b432016-11-30 13:51:28 -0700447 mCurrentDataSpace = item.mDataSpace;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800448 mCurrentFence = item.mFence;
Brian Anderson3d4039d2016-09-23 16:31:30 -0700449 mCurrentFenceTime = item.mFenceTime;
Eino-Ville Talvalad171da92013-09-19 13:36:07 -0700450 mCurrentFrameNumber = item.mFrameNumber;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800451
452 computeCurrentTransformMatrixLocked();
453
454 return err;
455}
456
Andy McFadden2adaf042012-12-18 09:49:45 -0800457status_t GLConsumer::bindTextureImageLocked() {
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800458 if (mEglDisplay == EGL_NO_DISPLAY) {
459 ALOGE("bindTextureImage: invalid display");
460 return INVALID_OPERATION;
461 }
462
Dan Stozad723bd72014-11-18 10:24:03 -0800463 GLenum error;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800464 while ((error = glGetError()) != GL_NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800465 GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800466 }
467
468 glBindTexture(mTexTarget, mTexName);
Eric Penner5c3d2432014-07-11 19:08:04 -0700469 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
Yi Kong48a619f2018-06-05 16:34:59 -0700470 mCurrentTextureImage == nullptr) {
Dan Stozad723bd72014-11-18 10:24:03 -0800471 GLC_LOGE("bindTextureImage: no currently-bound texture");
Eric Penner5c3d2432014-07-11 19:08:04 -0700472 return NO_INIT;
473 }
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800474
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700475 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay);
Eric Penner5c3d2432014-07-11 19:08:04 -0700476 if (err != NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800477 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
Eric Penner5c3d2432014-07-11 19:08:04 -0700478 mEglDisplay, mCurrentTexture);
479 return UNKNOWN_ERROR;
480 }
Eric Penner5c3d2432014-07-11 19:08:04 -0700481 mCurrentTextureImage->bindToTextureTarget(mTexTarget);
482
Eric Penner2d14a0e2014-08-25 20:16:37 -0700483 // In the rare case that the display is terminated and then initialized
484 // again, we can't detect that the display changed (it didn't), but the
485 // image is invalid. In this case, repeat the exact same steps while
486 // forcing the creation of a new image.
487 if ((error = glGetError()) != GL_NO_ERROR) {
488 glBindTexture(mTexTarget, mTexName);
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700489 status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, true);
Dan Stozad723bd72014-11-18 10:24:03 -0800490 if (result != NO_ERROR) {
491 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
Eric Penner2d14a0e2014-08-25 20:16:37 -0700492 mEglDisplay, mCurrentTexture);
493 return UNKNOWN_ERROR;
494 }
495 mCurrentTextureImage->bindToTextureTarget(mTexTarget);
496 if ((error = glGetError()) != GL_NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800497 GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
Eric Penner2d14a0e2014-08-25 20:16:37 -0700498 return UNKNOWN_ERROR;
499 }
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800500 }
Andy McFadden97eba892012-12-11 15:21:45 -0800501
502 // Wait for the new buffer to be ready.
503 return doGLFenceWaitLocked();
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800504}
505
Mathias Agopian45155962013-08-08 18:16:21 -0700506status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
Jamie Gennisce561372012-03-19 18:33:05 -0700507 EGLDisplay dpy = eglGetCurrentDisplay();
508 EGLContext ctx = eglGetCurrentContext();
509
Mathias Agopian45155962013-08-08 18:16:21 -0700510 if (!contextCheck) {
511 // if this is the first time we're called, mEglDisplay/mEglContext have
512 // never been set, so don't error out (below).
513 if (mEglDisplay == EGL_NO_DISPLAY) {
514 mEglDisplay = dpy;
515 }
Jesse Hall46a1f6b2014-08-06 12:15:15 -0700516 if (mEglContext == EGL_NO_CONTEXT) {
Mathias Agopian45155962013-08-08 18:16:21 -0700517 mEglContext = ctx;
518 }
519 }
520
521 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
Dan Stozad723bd72014-11-18 10:24:03 -0800522 GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
Jamie Gennis74bed552012-03-28 19:05:54 -0700523 return INVALID_OPERATION;
Jamie Gennisce561372012-03-19 18:33:05 -0700524 }
525
Mathias Agopian45155962013-08-08 18:16:21 -0700526 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
Dan Stozad723bd72014-11-18 10:24:03 -0800527 GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
Jamie Gennis74bed552012-03-28 19:05:54 -0700528 return INVALID_OPERATION;
Jamie Gennisce561372012-03-19 18:33:05 -0700529 }
530
531 mEglDisplay = dpy;
532 mEglContext = ctx;
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800533 return NO_ERROR;
Jamie Gennis8ba32fa2010-12-20 11:27:26 -0800534}
535
Jesse Hall13f01cb2013-03-20 11:37:21 -0700536void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
537 if (fence->isValid() &&
538 mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700539 status_t err = addReleaseFence(mCurrentTexture,
Eric Penner5c3d2432014-07-11 19:08:04 -0700540 mCurrentTextureImage->graphicBuffer(), fence);
Jesse Hall13f01cb2013-03-20 11:37:21 -0700541 if (err != OK) {
Dan Stozad723bd72014-11-18 10:24:03 -0800542 GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
Jesse Hall13f01cb2013-03-20 11:37:21 -0700543 strerror(-err), err);
544 }
Jesse Hallef194142012-06-14 14:45:17 -0700545 }
546}
547
Andy McFadden2adaf042012-12-18 09:49:45 -0800548status_t GLConsumer::detachFromContext() {
Jamie Gennis74bed552012-03-28 19:05:54 -0700549 ATRACE_CALL();
Dan Stozad723bd72014-11-18 10:24:03 -0800550 GLC_LOGV("detachFromContext");
Jamie Gennis74bed552012-03-28 19:05:54 -0700551 Mutex::Autolock lock(mMutex);
552
553 if (mAbandoned) {
Dan Stozad723bd72014-11-18 10:24:03 -0800554 GLC_LOGE("detachFromContext: abandoned GLConsumer");
Jamie Gennis74bed552012-03-28 19:05:54 -0700555 return NO_INIT;
556 }
557
558 if (!mAttached) {
Dan Stozad723bd72014-11-18 10:24:03 -0800559 GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
Jamie Gennis74bed552012-03-28 19:05:54 -0700560 "context");
561 return INVALID_OPERATION;
562 }
563
564 EGLDisplay dpy = eglGetCurrentDisplay();
565 EGLContext ctx = eglGetCurrentContext();
566
567 if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
Dan Stozad723bd72014-11-18 10:24:03 -0800568 GLC_LOGE("detachFromContext: invalid current EGLDisplay");
Jamie Gennis74bed552012-03-28 19:05:54 -0700569 return INVALID_OPERATION;
570 }
571
572 if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
Dan Stozad723bd72014-11-18 10:24:03 -0800573 GLC_LOGE("detachFromContext: invalid current EGLContext");
Jamie Gennis74bed552012-03-28 19:05:54 -0700574 return INVALID_OPERATION;
575 }
576
577 if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
578 status_t err = syncForReleaseLocked(dpy);
579 if (err != OK) {
580 return err;
581 }
582
583 glDeleteTextures(1, &mTexName);
584 }
585
586 mEglDisplay = EGL_NO_DISPLAY;
587 mEglContext = EGL_NO_CONTEXT;
588 mAttached = false;
589
590 return OK;
591}
592
Mathias Agopian3f844832013-08-07 21:24:32 -0700593status_t GLConsumer::attachToContext(uint32_t tex) {
Jamie Gennis74bed552012-03-28 19:05:54 -0700594 ATRACE_CALL();
Dan Stozad723bd72014-11-18 10:24:03 -0800595 GLC_LOGV("attachToContext");
Jamie Gennis74bed552012-03-28 19:05:54 -0700596 Mutex::Autolock lock(mMutex);
597
598 if (mAbandoned) {
Dan Stozad723bd72014-11-18 10:24:03 -0800599 GLC_LOGE("attachToContext: abandoned GLConsumer");
Jamie Gennis74bed552012-03-28 19:05:54 -0700600 return NO_INIT;
601 }
602
603 if (mAttached) {
Dan Stozad723bd72014-11-18 10:24:03 -0800604 GLC_LOGE("attachToContext: GLConsumer is already attached to a "
Jamie Gennis74bed552012-03-28 19:05:54 -0700605 "context");
606 return INVALID_OPERATION;
607 }
608
609 EGLDisplay dpy = eglGetCurrentDisplay();
610 EGLContext ctx = eglGetCurrentContext();
611
612 if (dpy == EGL_NO_DISPLAY) {
Dan Stozad723bd72014-11-18 10:24:03 -0800613 GLC_LOGE("attachToContext: invalid current EGLDisplay");
Jamie Gennis74bed552012-03-28 19:05:54 -0700614 return INVALID_OPERATION;
615 }
616
617 if (ctx == EGL_NO_CONTEXT) {
Dan Stozad723bd72014-11-18 10:24:03 -0800618 GLC_LOGE("attachToContext: invalid current EGLContext");
Jamie Gennis74bed552012-03-28 19:05:54 -0700619 return INVALID_OPERATION;
620 }
621
622 // We need to bind the texture regardless of whether there's a current
623 // buffer.
Mathias Agopian3f844832013-08-07 21:24:32 -0700624 glBindTexture(mTexTarget, GLuint(tex));
Jamie Gennis74bed552012-03-28 19:05:54 -0700625
Jamie Gennis74bed552012-03-28 19:05:54 -0700626 mEglDisplay = dpy;
627 mEglContext = ctx;
628 mTexName = tex;
629 mAttached = true;
630
Yi Kong48a619f2018-06-05 16:34:59 -0700631 if (mCurrentTextureImage != nullptr) {
Eric Penner5c3d2432014-07-11 19:08:04 -0700632 // This may wait for a buffer a second time. This is likely required if
633 // this is a different context, since otherwise the wait could be skipped
634 // by bouncing through another context. For the same context the extra
635 // wait is redundant.
636 status_t err = bindTextureImageLocked();
637 if (err != NO_ERROR) {
638 return err;
639 }
640 }
641
Jamie Gennis74bed552012-03-28 19:05:54 -0700642 return OK;
643}
644
Andy McFaddenbf974ab2012-12-04 16:51:15 -0800645
Andy McFadden2adaf042012-12-18 09:49:45 -0800646status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
Dan Stozad723bd72014-11-18 10:24:03 -0800647 GLC_LOGV("syncForReleaseLocked");
Jamie Gennis74bed552012-03-28 19:05:54 -0700648
Jamie Gennis01dbf552012-09-06 14:54:19 -0700649 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
Mathias Agopianca088332013-03-28 17:44:13 -0700650 if (SyncFeatures::getInstance().useNativeFenceSync()) {
Jamie Gennis01dbf552012-09-06 14:54:19 -0700651 EGLSyncKHR sync = eglCreateSyncKHR(dpy,
Yi Kong48a619f2018-06-05 16:34:59 -0700652 EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
Jamie Gennis01dbf552012-09-06 14:54:19 -0700653 if (sync == EGL_NO_SYNC_KHR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800654 GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
Jamie Gennis01dbf552012-09-06 14:54:19 -0700655 eglGetError());
Jamie Gennis74bed552012-03-28 19:05:54 -0700656 return UNKNOWN_ERROR;
Jamie Gennis74bed552012-03-28 19:05:54 -0700657 }
Jamie Gennis01dbf552012-09-06 14:54:19 -0700658 glFlush();
659 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
Jamie Gennis98ff0592012-09-10 14:49:42 -0700660 eglDestroySyncKHR(dpy, sync);
Jamie Gennis01dbf552012-09-06 14:54:19 -0700661 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
Dan Stozad723bd72014-11-18 10:24:03 -0800662 GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
Jamie Gennis01dbf552012-09-06 14:54:19 -0700663 "fd: %#x", eglGetError());
664 return UNKNOWN_ERROR;
665 }
666 sp<Fence> fence(new Fence(fenceFd));
Lajos Molnarc5d7b7d2013-05-03 14:50:50 -0700667 status_t err = addReleaseFenceLocked(mCurrentTexture,
Eric Penner5c3d2432014-07-11 19:08:04 -0700668 mCurrentTextureImage->graphicBuffer(), fence);
Jamie Gennis01dbf552012-09-06 14:54:19 -0700669 if (err != OK) {
Dan Stozad723bd72014-11-18 10:24:03 -0800670 GLC_LOGE("syncForReleaseLocked: error adding release fence: "
Jamie Gennis01dbf552012-09-06 14:54:19 -0700671 "%s (%d)", strerror(-err), err);
672 return err;
673 }
Mathias Agopianca088332013-03-28 17:44:13 -0700674 } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
Jamie Gennis01dbf552012-09-06 14:54:19 -0700675 EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
676 if (fence != EGL_NO_SYNC_KHR) {
677 // There is already a fence for the current slot. We need to
678 // wait on that before replacing it with another fence to
679 // ensure that all outstanding buffer accesses have completed
680 // before the producer accesses it.
681 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
682 if (result == EGL_FALSE) {
Dan Stozad723bd72014-11-18 10:24:03 -0800683 GLC_LOGE("syncForReleaseLocked: error waiting for previous "
Jamie Gennis01dbf552012-09-06 14:54:19 -0700684 "fence: %#x", eglGetError());
685 return UNKNOWN_ERROR;
686 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800687 GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
Jamie Gennis01dbf552012-09-06 14:54:19 -0700688 "fence");
689 return TIMED_OUT;
690 }
691 eglDestroySyncKHR(dpy, fence);
692 }
Jamie Gennis74bed552012-03-28 19:05:54 -0700693
Jamie Gennis01dbf552012-09-06 14:54:19 -0700694 // Create a fence for the outstanding accesses in the current
695 // OpenGL ES context.
Yi Kong48a619f2018-06-05 16:34:59 -0700696 fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
Jamie Gennis01dbf552012-09-06 14:54:19 -0700697 if (fence == EGL_NO_SYNC_KHR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800698 GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
Jamie Gennis01dbf552012-09-06 14:54:19 -0700699 eglGetError());
700 return UNKNOWN_ERROR;
701 }
702 glFlush();
703 mEglSlots[mCurrentTexture].mEglFence = fence;
Jamie Gennis74bed552012-03-28 19:05:54 -0700704 }
Jamie Gennis74bed552012-03-28 19:05:54 -0700705 }
706
707 return OK;
708}
709
Mathias Agopian3f844832013-08-07 21:24:32 -0700710uint32_t GLConsumer::getCurrentTextureTarget() const {
Jamie Gennisfb1b5a22011-09-28 12:13:31 -0700711 return mTexTarget;
Mathias Agopian7a042bf2011-04-11 21:19:55 -0700712}
713
Andy McFadden2adaf042012-12-18 09:49:45 -0800714void GLConsumer::getTransformMatrix(float mtx[16]) {
Jamie Gennisf238e282011-01-09 16:33:17 -0800715 Mutex::Autolock lock(mMutex);
Jamie Gennis736aa952011-06-12 17:03:06 -0700716 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
717}
718
Andy McFadden2adaf042012-12-18 09:49:45 -0800719void GLConsumer::setFilteringEnabled(bool enabled) {
Jamie Gennis5c1139f2012-05-08 16:56:34 -0700720 Mutex::Autolock lock(mMutex);
Mathias Agopiane96e9e12012-09-24 19:26:11 -0700721 if (mAbandoned) {
Dan Stozad723bd72014-11-18 10:24:03 -0800722 GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
Mathias Agopiane96e9e12012-09-24 19:26:11 -0700723 return;
724 }
Jamie Gennis5c1139f2012-05-08 16:56:34 -0700725 bool needsRecompute = mFilteringEnabled != enabled;
726 mFilteringEnabled = enabled;
Mathias Agopiane96e9e12012-09-24 19:26:11 -0700727
Yi Kong48a619f2018-06-05 16:34:59 -0700728 if (needsRecompute && mCurrentTextureImage==nullptr) {
Dan Stozad723bd72014-11-18 10:24:03 -0800729 GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
Mathias Agopiane96e9e12012-09-24 19:26:11 -0700730 }
731
Yi Kong48a619f2018-06-05 16:34:59 -0700732 if (needsRecompute && mCurrentTextureImage != nullptr) {
Mathias Agopiane96e9e12012-09-24 19:26:11 -0700733 computeCurrentTransformMatrixLocked();
Jamie Gennis5c1139f2012-05-08 16:56:34 -0700734 }
735}
736
Andy McFadden2adaf042012-12-18 09:49:45 -0800737void GLConsumer::computeCurrentTransformMatrixLocked() {
Dan Stozad723bd72014-11-18 10:24:03 -0800738 GLC_LOGV("computeCurrentTransformMatrixLocked");
John Reck1a61da52016-04-28 13:18:15 -0700739 sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
740 nullptr : mCurrentTextureImage->graphicBuffer();
741 if (buf == nullptr) {
742 GLC_LOGD("computeCurrentTransformMatrixLocked: "
743 "mCurrentTextureImage is NULL");
744 }
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700745 computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop,
John Reck1a61da52016-04-28 13:18:15 -0700746 mCurrentTransform, mFilteringEnabled);
747}
748
Chia-I Wu93b122f2017-12-01 08:51:39 -0800749Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
750 Rect outCrop = crop;
751
752 uint32_t newWidth = static_cast<uint32_t>(crop.width());
753 uint32_t newHeight = static_cast<uint32_t>(crop.height());
754
755 if (newWidth * bufferHeight > newHeight * bufferWidth) {
756 newWidth = newHeight * bufferWidth / bufferHeight;
757 ALOGV("too wide: newWidth = %d", newWidth);
758 } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
759 newHeight = newWidth * bufferHeight / bufferWidth;
760 ALOGV("too tall: newHeight = %d", newHeight);
761 }
762
763 uint32_t currentWidth = static_cast<uint32_t>(crop.width());
764 uint32_t currentHeight = static_cast<uint32_t>(crop.height());
765
766 // The crop is too wide
767 if (newWidth < currentWidth) {
768 uint32_t dw = currentWidth - newWidth;
769 auto halfdw = dw / 2;
770 outCrop.left += halfdw;
771 // Not halfdw because it would subtract 1 too few when dw is odd
772 outCrop.right -= (dw - halfdw);
773 // The crop is too tall
774 } else if (newHeight < currentHeight) {
775 uint32_t dh = currentHeight - newHeight;
776 auto halfdh = dh / 2;
777 outCrop.top += halfdh;
778 // Not halfdh because it would subtract 1 too few when dh is odd
779 outCrop.bottom -= (dh - halfdh);
780 }
781
782 ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
783 outCrop.left, outCrop.top,
784 outCrop.right,outCrop.bottom);
785
786 return outCrop;
787}
788
Andy McFadden2adaf042012-12-18 09:49:45 -0800789nsecs_t GLConsumer::getTimestamp() {
Dan Stozad723bd72014-11-18 10:24:03 -0800790 GLC_LOGV("getTimestamp");
Eino-Ville Talvala1d01a122011-02-18 11:02:42 -0800791 Mutex::Autolock lock(mMutex);
792 return mCurrentTimestamp;
793}
794
Courtney Goeltzenleuchterbb09b432016-11-30 13:51:28 -0700795android_dataspace GLConsumer::getCurrentDataSpace() {
796 GLC_LOGV("getCurrentDataSpace");
797 Mutex::Autolock lock(mMutex);
798 return mCurrentDataSpace;
799}
800
Dan Stozad723bd72014-11-18 10:24:03 -0800801uint64_t GLConsumer::getFrameNumber() {
802 GLC_LOGV("getFrameNumber");
Eino-Ville Talvalad171da92013-09-19 13:36:07 -0700803 Mutex::Autolock lock(mMutex);
804 return mCurrentFrameNumber;
805}
806
Chia-I Wu06d63de2017-01-04 14:58:51 +0800807sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
Mathias Agopian7a042bf2011-04-11 21:19:55 -0700808 Mutex::Autolock lock(mMutex);
Chia-I Wu06d63de2017-01-04 14:58:51 +0800809
810 if (outSlot != nullptr) {
811 *outSlot = mCurrentTexture;
812 }
813
814 return (mCurrentTextureImage == nullptr) ?
Yi Kong48a619f2018-06-05 16:34:59 -0700815 nullptr : mCurrentTextureImage->graphicBuffer();
Mathias Agopian7a042bf2011-04-11 21:19:55 -0700816}
817
Andy McFadden2adaf042012-12-18 09:49:45 -0800818Rect GLConsumer::getCurrentCrop() const {
Mathias Agopian7a042bf2011-04-11 21:19:55 -0700819 Mutex::Autolock lock(mMutex);
Chia-I Wu93b122f2017-12-01 08:51:39 -0800820 return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
821 ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
822 : mCurrentCrop;
Mathias Agopian7a042bf2011-04-11 21:19:55 -0700823}
824
Andy McFadden2adaf042012-12-18 09:49:45 -0800825uint32_t GLConsumer::getCurrentTransform() const {
Mathias Agopian7a042bf2011-04-11 21:19:55 -0700826 Mutex::Autolock lock(mMutex);
827 return mCurrentTransform;
828}
829
Andy McFadden2adaf042012-12-18 09:49:45 -0800830uint32_t GLConsumer::getCurrentScalingMode() const {
Mathias Agopian7734ebf2011-07-13 15:24:42 -0700831 Mutex::Autolock lock(mMutex);
832 return mCurrentScalingMode;
833}
834
Andy McFadden2adaf042012-12-18 09:49:45 -0800835sp<Fence> GLConsumer::getCurrentFence() const {
Jesse Halldc5b4852012-06-29 15:21:18 -0700836 Mutex::Autolock lock(mMutex);
837 return mCurrentFence;
838}
839
Brian Anderson3d4039d2016-09-23 16:31:30 -0700840std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
841 Mutex::Autolock lock(mMutex);
842 return mCurrentFenceTime;
843}
844
Andy McFadden2adaf042012-12-18 09:49:45 -0800845status_t GLConsumer::doGLFenceWaitLocked() const {
Jamie Gennis61e04b92012-09-09 17:48:42 -0700846
847 EGLDisplay dpy = eglGetCurrentDisplay();
848 EGLContext ctx = eglGetCurrentContext();
849
850 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
Dan Stozad723bd72014-11-18 10:24:03 -0800851 GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
Jamie Gennis61e04b92012-09-09 17:48:42 -0700852 return INVALID_OPERATION;
853 }
854
855 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
Dan Stozad723bd72014-11-18 10:24:03 -0800856 GLC_LOGE("doGLFenceWait: invalid current EGLContext");
Jamie Gennis61e04b92012-09-09 17:48:42 -0700857 return INVALID_OPERATION;
858 }
859
Jamie Gennis1df8c342012-12-20 14:05:45 -0800860 if (mCurrentFence->isValid()) {
Jeffrey Kardatzkea45e1c82018-03-13 12:07:28 -0700861 if (SyncFeatures::getInstance().useWaitSync() &&
862 SyncFeatures::getInstance().useNativeFenceSync()) {
Jamie Gennis61e04b92012-09-09 17:48:42 -0700863 // Create an EGLSyncKHR from the current fence.
864 int fenceFd = mCurrentFence->dup();
865 if (fenceFd == -1) {
Dan Stozad723bd72014-11-18 10:24:03 -0800866 GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
Jamie Gennis61e04b92012-09-09 17:48:42 -0700867 return -errno;
868 }
869 EGLint attribs[] = {
870 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
871 EGL_NONE
872 };
873 EGLSyncKHR sync = eglCreateSyncKHR(dpy,
874 EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
875 if (sync == EGL_NO_SYNC_KHR) {
876 close(fenceFd);
Dan Stozad723bd72014-11-18 10:24:03 -0800877 GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
Jamie Gennis61e04b92012-09-09 17:48:42 -0700878 eglGetError());
879 return UNKNOWN_ERROR;
880 }
881
882 // XXX: The spec draft is inconsistent as to whether this should
883 // return an EGLint or void. Ignore the return value for now, as
884 // it's not strictly needed.
Mathias Agopian2bb71682013-03-27 17:32:41 -0700885 eglWaitSyncKHR(dpy, sync, 0);
Jamie Gennis61e04b92012-09-09 17:48:42 -0700886 EGLint eglErr = eglGetError();
887 eglDestroySyncKHR(dpy, sync);
888 if (eglErr != EGL_SUCCESS) {
Dan Stozad723bd72014-11-18 10:24:03 -0800889 GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
Jamie Gennis61e04b92012-09-09 17:48:42 -0700890 eglErr);
891 return UNKNOWN_ERROR;
892 }
893 } else {
Mathias Agopianea74d3b2013-05-16 18:03:22 -0700894 status_t err = mCurrentFence->waitForever(
Andy McFadden2adaf042012-12-18 09:49:45 -0800895 "GLConsumer::doGLFenceWaitLocked");
Jamie Gennis61e04b92012-09-09 17:48:42 -0700896 if (err != NO_ERROR) {
Dan Stozad723bd72014-11-18 10:24:03 -0800897 GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
Jamie Gennis61e04b92012-09-09 17:48:42 -0700898 return err;
899 }
900 }
901 }
902
903 return NO_ERROR;
904}
905
Andy McFadden2adaf042012-12-18 09:49:45 -0800906void GLConsumer::freeBufferLocked(int slotIndex) {
Dan Stozad723bd72014-11-18 10:24:03 -0800907 GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
Daniel Lam9abe1eb2012-03-26 20:37:15 -0700908 if (slotIndex == mCurrentTexture) {
909 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
910 }
Eric Penner5c3d2432014-07-11 19:08:04 -0700911 mEglSlots[slotIndex].mEglImage.clear();
Jamie Gennis9fea3422012-08-07 18:03:04 -0700912 ConsumerBase::freeBufferLocked(slotIndex);
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700913}
Daniel Lameae59d22012-01-22 15:26:27 -0800914
Andy McFadden2adaf042012-12-18 09:49:45 -0800915void GLConsumer::abandonLocked() {
Dan Stozad723bd72014-11-18 10:24:03 -0800916 GLC_LOGV("abandonLocked");
Eric Penner5c3d2432014-07-11 19:08:04 -0700917 mCurrentTextureImage.clear();
Jamie Gennis9fea3422012-08-07 18:03:04 -0700918 ConsumerBase::abandonLocked();
Jamie Gennis7b305ff2011-07-19 12:08:33 -0700919}
920
Chia-I Wue2786ea2017-08-07 10:36:08 -0700921status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
Chia-I Wua81bc492017-11-27 10:16:00 -0800922 return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700923}
924
Mathias Agopian74d211a2013-04-22 16:55:35 +0200925void GLConsumer::dumpLocked(String8& result, const char* prefix) const
Mathias Agopian68c77942011-05-09 19:08:33 -0700926{
Mathias Agopian74d211a2013-04-22 16:55:35 +0200927 result.appendFormat(
Jamie Gennis9fea3422012-08-07 18:03:04 -0700928 "%smTexName=%d mCurrentTexture=%d\n"
929 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
930 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
931 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
932 mCurrentTransform);
Mathias Agopian68c77942011-05-09 19:08:33 -0700933
Mathias Agopian74d211a2013-04-22 16:55:35 +0200934 ConsumerBase::dumpLocked(result, prefix);
Mathias Agopian68c77942011-05-09 19:08:33 -0700935}
936
Eric Penner5c3d2432014-07-11 19:08:04 -0700937GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
938 mGraphicBuffer(graphicBuffer),
939 mEglImage(EGL_NO_IMAGE_KHR),
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700940 mEglDisplay(EGL_NO_DISPLAY) {
Eric Penner5c3d2432014-07-11 19:08:04 -0700941}
942
943GLConsumer::EglImage::~EglImage() {
944 if (mEglImage != EGL_NO_IMAGE_KHR) {
945 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
946 ALOGE("~EglImage: eglDestroyImageKHR failed");
947 }
Ady Abrahama3b08ef2019-07-15 18:43:10 -0700948 DEBUG_EGL_IMAGE_TRACKER_DESTROY();
Michael Lentine78be65e2014-10-02 12:10:07 -0700949 eglTerminate(mEglDisplay);
Eric Penner5c3d2432014-07-11 19:08:04 -0700950 }
951}
952
953status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
Eric Penner2d14a0e2014-08-25 20:16:37 -0700954 bool forceCreation) {
Eric Penner5c3d2432014-07-11 19:08:04 -0700955 // If there's an image and it's no longer valid, destroy it.
956 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
957 bool displayInvalid = mEglDisplay != eglDisplay;
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700958 if (haveImage && (displayInvalid || forceCreation)) {
Eric Penner5c3d2432014-07-11 19:08:04 -0700959 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
960 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
961 }
Ady Abrahama3b08ef2019-07-15 18:43:10 -0700962 DEBUG_EGL_IMAGE_TRACKER_DESTROY();
Michael Lentine78be65e2014-10-02 12:10:07 -0700963 eglTerminate(mEglDisplay);
Eric Penner5c3d2432014-07-11 19:08:04 -0700964 mEglImage = EGL_NO_IMAGE_KHR;
965 mEglDisplay = EGL_NO_DISPLAY;
966 }
967
968 // If there's no image, create one.
969 if (mEglImage == EGL_NO_IMAGE_KHR) {
970 mEglDisplay = eglDisplay;
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700971 mEglImage = createImage(mEglDisplay, mGraphicBuffer);
Eric Penner5c3d2432014-07-11 19:08:04 -0700972 }
973
974 // Fail if we can't create a valid image.
975 if (mEglImage == EGL_NO_IMAGE_KHR) {
976 mEglDisplay = EGL_NO_DISPLAY;
Eric Penner5c3d2432014-07-11 19:08:04 -0700977 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700978 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
Eric Penner5c3d2432014-07-11 19:08:04 -0700979 buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
980 buffer->getUsage(), buffer->getPixelFormat());
981 return UNKNOWN_ERROR;
982 }
983
984 return OK;
985}
986
987void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
Dan Stozad723bd72014-11-18 10:24:03 -0800988 glEGLImageTargetTexture2DOES(texTarget,
989 static_cast<GLeglImageOES>(mEglImage));
Eric Penner5c3d2432014-07-11 19:08:04 -0700990}
991
992EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
Krzysztof Kosiński7108c312018-06-27 19:12:54 -0700993 const sp<GraphicBuffer>& graphicBuffer) {
Dan Stozad723bd72014-11-18 10:24:03 -0800994 EGLClientBuffer cbuf =
995 static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
Craig Donneraec86972016-04-28 18:09:40 -0700996 const bool createProtectedImage =
997 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
998 hasEglProtectedContent();
Eric Penner5c3d2432014-07-11 19:08:04 -0700999 EGLint attrs[] = {
Krzysztof Kosiński7108c312018-06-27 19:12:54 -07001000 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
Craig Donneraec86972016-04-28 18:09:40 -07001001 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1002 createProtectedImage ? EGL_TRUE : EGL_NONE,
Eric Penner5c3d2432014-07-11 19:08:04 -07001003 EGL_NONE,
1004 };
Yi Kong48a619f2018-06-05 16:34:59 -07001005 eglInitialize(dpy, nullptr, nullptr);
Eric Penner5c3d2432014-07-11 19:08:04 -07001006 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
1007 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
1008 if (image == EGL_NO_IMAGE_KHR) {
1009 EGLint error = eglGetError();
1010 ALOGE("error creating EGLImage: %#x", error);
Michael Lentine78be65e2014-10-02 12:10:07 -07001011 eglTerminate(dpy);
Ady Abrahama3b08ef2019-07-15 18:43:10 -07001012 } else {
1013 DEBUG_EGL_IMAGE_TRACKER_CREATE();
Eric Penner5c3d2432014-07-11 19:08:04 -07001014 }
Ady Abrahama3b08ef2019-07-15 18:43:10 -07001015
Eric Penner5c3d2432014-07-11 19:08:04 -07001016 return image;
1017}
1018
Jamie Gennis8ba32fa2010-12-20 11:27:26 -08001019}; // namespace android