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