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