• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gui/BufferItem.h>
35 #include <gui/GLConsumer.h>
36 #include <gui/ISurfaceComposer.h>
37 #include <gui/SurfaceComposerClient.h>
38 
39 #include <private/gui/ComposerService.h>
40 #include <private/gui/SyncFeatures.h>
41 
42 #include <utils/Log.h>
43 #include <utils/String8.h>
44 #include <utils/Trace.h>
45 
46 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
47 #define CROP_EXT_STR "EGL_ANDROID_image_crop"
48 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
49 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
50 
51 namespace android {
52 
53 // Macros for including the GLConsumer name in log messages
54 #define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
55 #define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
56 //#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
57 #define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
58 #define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
59 
60 static const struct {
61     uint32_t width, height;
62     char const* bits;
63 } kDebugData = { 15, 12,
64     "_______________"
65     "_______________"
66     "_____XX_XX_____"
67     "__X_X_____X_X__"
68     "__X_XXXXXXX_X__"
69     "__XXXXXXXXXXX__"
70     "___XX_XXX_XX___"
71     "____XXXXXXX____"
72     "_____X___X_____"
73     "____X_____X____"
74     "_______________"
75     "_______________"
76 };
77 
78 // Transform matrices
79 static float mtxIdentity[16] = {
80     1, 0, 0, 0,
81     0, 1, 0, 0,
82     0, 0, 1, 0,
83     0, 0, 0, 1,
84 };
85 static float mtxFlipH[16] = {
86     -1, 0, 0, 0,
87     0, 1, 0, 0,
88     0, 0, 1, 0,
89     1, 0, 0, 1,
90 };
91 static float mtxFlipV[16] = {
92     1, 0, 0, 0,
93     0, -1, 0, 0,
94     0, 0, 1, 0,
95     0, 1, 0, 1,
96 };
97 static float mtxRot90[16] = {
98     0, 1, 0, 0,
99     -1, 0, 0, 0,
100     0, 0, 1, 0,
101     1, 0, 0, 1,
102 };
103 
104 static void mtxMul(float out[16], const float a[16], const float b[16]);
105 
106 Mutex GLConsumer::sStaticInitLock;
107 sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
108 
hasEglAndroidImageCropImpl()109 static bool hasEglAndroidImageCropImpl() {
110     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
111     const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
112     size_t cropExtLen = strlen(CROP_EXT_STR);
113     size_t extsLen = strlen(exts);
114     bool equal = !strcmp(CROP_EXT_STR, exts);
115     bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
116     bool atEnd = (cropExtLen+1) < extsLen &&
117             !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
118     bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
119     return equal || atStart || atEnd || inMiddle;
120 }
121 
hasEglAndroidImageCrop()122 static bool hasEglAndroidImageCrop() {
123     // Only compute whether the extension is present once the first time this
124     // function is called.
125     static bool hasIt = hasEglAndroidImageCropImpl();
126     return hasIt;
127 }
128 
hasEglProtectedContentImpl()129 static bool hasEglProtectedContentImpl() {
130     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
131     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
132     size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
133     size_t extsLen = strlen(exts);
134     bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
135     bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
136     bool atEnd = (cropExtLen+1) < extsLen &&
137             !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
138     bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
139     return equal || atStart || atEnd || inMiddle;
140 }
141 
hasEglProtectedContent()142 static bool hasEglProtectedContent() {
143     // Only compute whether the extension is present once the first time this
144     // function is called.
145     static bool hasIt = hasEglProtectedContentImpl();
146     return hasIt;
147 }
148 
isEglImageCroppable(const Rect & crop)149 static bool isEglImageCroppable(const Rect& crop) {
150     return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
151 }
152 
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)153 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
154         uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
155     ConsumerBase(bq, isControlledByApp),
156     mCurrentCrop(Rect::EMPTY_RECT),
157     mCurrentTransform(0),
158     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
159     mCurrentFence(Fence::NO_FENCE),
160     mCurrentTimestamp(0),
161     mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
162     mCurrentFrameNumber(0),
163     mDefaultWidth(1),
164     mDefaultHeight(1),
165     mFilteringEnabled(true),
166     mTexName(tex),
167     mUseFenceSync(useFenceSync),
168     mTexTarget(texTarget),
169     mEglDisplay(EGL_NO_DISPLAY),
170     mEglContext(EGL_NO_CONTEXT),
171     mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
172     mAttached(true)
173 {
174     GLC_LOGV("GLConsumer");
175 
176     memcpy(mCurrentTransformMatrix, mtxIdentity,
177             sizeof(mCurrentTransformMatrix));
178 
179     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
180 }
181 
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)182 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
183         bool useFenceSync, bool isControlledByApp) :
184     ConsumerBase(bq, isControlledByApp),
185     mCurrentCrop(Rect::EMPTY_RECT),
186     mCurrentTransform(0),
187     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
188     mCurrentFence(Fence::NO_FENCE),
189     mCurrentTimestamp(0),
190     mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
191     mCurrentFrameNumber(0),
192     mDefaultWidth(1),
193     mDefaultHeight(1),
194     mFilteringEnabled(true),
195     mTexName(0),
196     mUseFenceSync(useFenceSync),
197     mTexTarget(texTarget),
198     mEglDisplay(EGL_NO_DISPLAY),
199     mEglContext(EGL_NO_CONTEXT),
200     mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
201     mAttached(false)
202 {
203     GLC_LOGV("GLConsumer");
204 
205     memcpy(mCurrentTransformMatrix, mtxIdentity,
206             sizeof(mCurrentTransformMatrix));
207 
208     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
209 }
210 
setDefaultBufferSize(uint32_t w,uint32_t h)211 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
212 {
213     Mutex::Autolock lock(mMutex);
214     if (mAbandoned) {
215         GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
216         return NO_INIT;
217     }
218     mDefaultWidth = w;
219     mDefaultHeight = h;
220     return mConsumer->setDefaultBufferSize(w, h);
221 }
222 
updateTexImage()223 status_t GLConsumer::updateTexImage() {
224     ATRACE_CALL();
225     GLC_LOGV("updateTexImage");
226     Mutex::Autolock lock(mMutex);
227 
228     if (mAbandoned) {
229         GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
230         return NO_INIT;
231     }
232 
233     // Make sure the EGL state is the same as in previous calls.
234     status_t err = checkAndUpdateEglStateLocked();
235     if (err != NO_ERROR) {
236         return err;
237     }
238 
239     BufferItem item;
240 
241     // Acquire the next buffer.
242     // In asynchronous mode the list is guaranteed to be one buffer
243     // deep, while in synchronous mode we use the oldest buffer.
244     err = acquireBufferLocked(&item, 0);
245     if (err != NO_ERROR) {
246         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
247             // We always bind the texture even if we don't update its contents.
248             GLC_LOGV("updateTexImage: no buffers were available");
249             glBindTexture(mTexTarget, mTexName);
250             err = NO_ERROR;
251         } else {
252             GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
253                 strerror(-err), err);
254         }
255         return err;
256     }
257 
258     // Release the previous buffer.
259     err = updateAndReleaseLocked(item);
260     if (err != NO_ERROR) {
261         // We always bind the texture.
262         glBindTexture(mTexTarget, mTexName);
263         return err;
264     }
265 
266     // Bind the new buffer to the GL texture, and wait until it's ready.
267     return bindTextureImageLocked();
268 }
269 
270 
releaseTexImage()271 status_t GLConsumer::releaseTexImage() {
272     ATRACE_CALL();
273     GLC_LOGV("releaseTexImage");
274     Mutex::Autolock lock(mMutex);
275 
276     if (mAbandoned) {
277         GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
278         return NO_INIT;
279     }
280 
281     // Make sure the EGL state is the same as in previous calls.
282     status_t err = NO_ERROR;
283 
284     if (mAttached) {
285         err = checkAndUpdateEglStateLocked(true);
286         if (err != NO_ERROR) {
287             return err;
288         }
289     } else {
290         // if we're detached, no need to validate EGL's state -- we won't use it.
291     }
292 
293     // Update the GLConsumer state.
294     int buf = mCurrentTexture;
295     if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
296 
297         GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
298 
299         if (mAttached) {
300             // Do whatever sync ops we need to do before releasing the slot.
301             err = syncForReleaseLocked(mEglDisplay);
302             if (err != NO_ERROR) {
303                 GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
304                 return err;
305             }
306         } else {
307             // if we're detached, we just use the fence that was created in detachFromContext()
308             // so... basically, nothing more to do here.
309         }
310 
311         err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
312         if (err < NO_ERROR) {
313             GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
314                     strerror(-err), err);
315             return err;
316         }
317 
318         if (mReleasedTexImage == NULL) {
319             mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
320         }
321 
322         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
323         mCurrentTextureImage = mReleasedTexImage;
324         mCurrentCrop.makeInvalid();
325         mCurrentTransform = 0;
326         mCurrentTimestamp = 0;
327         mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
328         mCurrentFence = Fence::NO_FENCE;
329         mCurrentFenceTime = FenceTime::NO_FENCE;
330 
331         if (mAttached) {
332             // This binds a dummy buffer (mReleasedTexImage).
333             status_t result = bindTextureImageLocked();
334             if (result != NO_ERROR) {
335                 return result;
336             }
337         } else {
338             // detached, don't touch the texture (and we may not even have an
339             // EGLDisplay here.
340         }
341     }
342 
343     return NO_ERROR;
344 }
345 
getDebugTexImageBuffer()346 sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
347     Mutex::Autolock _l(sStaticInitLock);
348     if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
349         // The first time, create the debug texture in case the application
350         // continues to use it.
351         sp<GraphicBuffer> buffer = new GraphicBuffer(
352                 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
353                 GraphicBuffer::USAGE_SW_WRITE_RARELY,
354                 "[GLConsumer debug texture]");
355         uint32_t* bits;
356         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
357         uint32_t stride = buffer->getStride();
358         uint32_t height = buffer->getHeight();
359         memset(bits, 0, stride * height * 4);
360         for (uint32_t y = 0; y < kDebugData.height; y++) {
361             for (uint32_t x = 0; x < kDebugData.width; x++) {
362                 bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
363                     0xFF000000 : 0xFFFFFFFF;
364             }
365             bits += stride;
366         }
367         buffer->unlock();
368         sReleasedTexImageBuffer = buffer;
369     }
370     return sReleasedTexImageBuffer;
371 }
372 
acquireBufferLocked(BufferItem * item,nsecs_t presentWhen,uint64_t maxFrameNumber)373 status_t GLConsumer::acquireBufferLocked(BufferItem *item,
374         nsecs_t presentWhen, uint64_t maxFrameNumber) {
375     status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
376             maxFrameNumber);
377     if (err != NO_ERROR) {
378         return err;
379     }
380 
381     // If item->mGraphicBuffer is not null, this buffer has not been acquired
382     // before, so any prior EglImage created is using a stale buffer. This
383     // replaces any old EglImage with a new one (using the new buffer).
384     if (item->mGraphicBuffer != NULL) {
385         int slot = item->mSlot;
386         mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
387     }
388 
389     return NO_ERROR;
390 }
391 
releaseBufferLocked(int buf,sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)392 status_t GLConsumer::releaseBufferLocked(int buf,
393         sp<GraphicBuffer> graphicBuffer,
394         EGLDisplay display, EGLSyncKHR eglFence) {
395     // release the buffer if it hasn't already been discarded by the
396     // BufferQueue. This can happen, for example, when the producer of this
397     // buffer has reallocated the original buffer slot after this buffer
398     // was acquired.
399     status_t err = ConsumerBase::releaseBufferLocked(
400             buf, graphicBuffer, display, eglFence);
401     mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
402     return err;
403 }
404 
updateAndReleaseLocked(const BufferItem & item,PendingRelease * pendingRelease)405 status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
406         PendingRelease* pendingRelease)
407 {
408     status_t err = NO_ERROR;
409 
410     int slot = item.mSlot;
411 
412     if (!mAttached) {
413         GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
414                 "ES context");
415         releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
416                 mEglDisplay, EGL_NO_SYNC_KHR);
417         return INVALID_OPERATION;
418     }
419 
420     // Confirm state.
421     err = checkAndUpdateEglStateLocked();
422     if (err != NO_ERROR) {
423         releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
424                 mEglDisplay, EGL_NO_SYNC_KHR);
425         return err;
426     }
427 
428     // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
429     // if nessessary, for the gralloc buffer currently in the slot in
430     // ConsumerBase.
431     // We may have to do this even when item.mGraphicBuffer == NULL (which
432     // means the buffer was previously acquired).
433     err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
434     if (err != NO_ERROR) {
435         GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
436                 mEglDisplay, slot);
437         releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
438                 mEglDisplay, EGL_NO_SYNC_KHR);
439         return UNKNOWN_ERROR;
440     }
441 
442     // Do whatever sync ops we need to do before releasing the old slot.
443     if (slot != mCurrentTexture) {
444         err = syncForReleaseLocked(mEglDisplay);
445         if (err != NO_ERROR) {
446             // Release the buffer we just acquired.  It's not safe to
447             // release the old buffer, so instead we just drop the new frame.
448             // As we are still under lock since acquireBuffer, it is safe to
449             // release by slot.
450             releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
451                     mEglDisplay, EGL_NO_SYNC_KHR);
452             return err;
453         }
454     }
455 
456     GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
457             mCurrentTexture, mCurrentTextureImage != NULL ?
458                     mCurrentTextureImage->graphicBufferHandle() : 0,
459             slot, mSlots[slot].mGraphicBuffer->handle);
460 
461     // Hang onto the pointer so that it isn't freed in the call to
462     // releaseBufferLocked() if we're in shared buffer mode and both buffers are
463     // the same.
464     sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
465 
466     // release old buffer
467     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
468         if (pendingRelease == nullptr) {
469             status_t status = releaseBufferLocked(
470                     mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
471                     mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
472             if (status < NO_ERROR) {
473                 GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
474                         strerror(-status), status);
475                 err = status;
476                 // keep going, with error raised [?]
477             }
478         } else {
479             pendingRelease->currentTexture = mCurrentTexture;
480             pendingRelease->graphicBuffer =
481                     mCurrentTextureImage->graphicBuffer();
482             pendingRelease->display = mEglDisplay;
483             pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
484             pendingRelease->isPending = true;
485         }
486     }
487 
488     // Update the GLConsumer state.
489     mCurrentTexture = slot;
490     mCurrentTextureImage = nextTextureImage;
491     mCurrentCrop = item.mCrop;
492     mCurrentTransform = item.mTransform;
493     mCurrentScalingMode = item.mScalingMode;
494     mCurrentTimestamp = item.mTimestamp;
495     mCurrentDataSpace = item.mDataSpace;
496     mCurrentFence = item.mFence;
497     mCurrentFenceTime = item.mFenceTime;
498     mCurrentFrameNumber = item.mFrameNumber;
499 
500     computeCurrentTransformMatrixLocked();
501 
502     return err;
503 }
504 
bindTextureImageLocked()505 status_t GLConsumer::bindTextureImageLocked() {
506     if (mEglDisplay == EGL_NO_DISPLAY) {
507         ALOGE("bindTextureImage: invalid display");
508         return INVALID_OPERATION;
509     }
510 
511     GLenum error;
512     while ((error = glGetError()) != GL_NO_ERROR) {
513         GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
514     }
515 
516     glBindTexture(mTexTarget, mTexName);
517     if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
518             mCurrentTextureImage == NULL) {
519         GLC_LOGE("bindTextureImage: no currently-bound texture");
520         return NO_INIT;
521     }
522 
523     status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
524                                                         mCurrentCrop);
525     if (err != NO_ERROR) {
526         GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
527                 mEglDisplay, mCurrentTexture);
528         return UNKNOWN_ERROR;
529     }
530     mCurrentTextureImage->bindToTextureTarget(mTexTarget);
531 
532     // In the rare case that the display is terminated and then initialized
533     // again, we can't detect that the display changed (it didn't), but the
534     // image is invalid. In this case, repeat the exact same steps while
535     // forcing the creation of a new image.
536     if ((error = glGetError()) != GL_NO_ERROR) {
537         glBindTexture(mTexTarget, mTexName);
538         status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay,
539                                                                mCurrentCrop,
540                                                                true);
541         if (result != NO_ERROR) {
542             GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
543                     mEglDisplay, mCurrentTexture);
544             return UNKNOWN_ERROR;
545         }
546         mCurrentTextureImage->bindToTextureTarget(mTexTarget);
547         if ((error = glGetError()) != GL_NO_ERROR) {
548             GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
549             return UNKNOWN_ERROR;
550         }
551     }
552 
553     // Wait for the new buffer to be ready.
554     return doGLFenceWaitLocked();
555 }
556 
checkAndUpdateEglStateLocked(bool contextCheck)557 status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
558     EGLDisplay dpy = eglGetCurrentDisplay();
559     EGLContext ctx = eglGetCurrentContext();
560 
561     if (!contextCheck) {
562         // if this is the first time we're called, mEglDisplay/mEglContext have
563         // never been set, so don't error out (below).
564         if (mEglDisplay == EGL_NO_DISPLAY) {
565             mEglDisplay = dpy;
566         }
567         if (mEglContext == EGL_NO_CONTEXT) {
568             mEglContext = ctx;
569         }
570     }
571 
572     if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
573         GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
574         return INVALID_OPERATION;
575     }
576 
577     if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
578         GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
579         return INVALID_OPERATION;
580     }
581 
582     mEglDisplay = dpy;
583     mEglContext = ctx;
584     return NO_ERROR;
585 }
586 
setReleaseFence(const sp<Fence> & fence)587 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
588     if (fence->isValid() &&
589             mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
590         status_t err = addReleaseFence(mCurrentTexture,
591                 mCurrentTextureImage->graphicBuffer(), fence);
592         if (err != OK) {
593             GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
594                     strerror(-err), err);
595         }
596     }
597 }
598 
detachFromContext()599 status_t GLConsumer::detachFromContext() {
600     ATRACE_CALL();
601     GLC_LOGV("detachFromContext");
602     Mutex::Autolock lock(mMutex);
603 
604     if (mAbandoned) {
605         GLC_LOGE("detachFromContext: abandoned GLConsumer");
606         return NO_INIT;
607     }
608 
609     if (!mAttached) {
610         GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
611                 "context");
612         return INVALID_OPERATION;
613     }
614 
615     EGLDisplay dpy = eglGetCurrentDisplay();
616     EGLContext ctx = eglGetCurrentContext();
617 
618     if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
619         GLC_LOGE("detachFromContext: invalid current EGLDisplay");
620         return INVALID_OPERATION;
621     }
622 
623     if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
624         GLC_LOGE("detachFromContext: invalid current EGLContext");
625         return INVALID_OPERATION;
626     }
627 
628     if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
629         status_t err = syncForReleaseLocked(dpy);
630         if (err != OK) {
631             return err;
632         }
633 
634         glDeleteTextures(1, &mTexName);
635     }
636 
637     mEglDisplay = EGL_NO_DISPLAY;
638     mEglContext = EGL_NO_CONTEXT;
639     mAttached = false;
640 
641     return OK;
642 }
643 
attachToContext(uint32_t tex)644 status_t GLConsumer::attachToContext(uint32_t tex) {
645     ATRACE_CALL();
646     GLC_LOGV("attachToContext");
647     Mutex::Autolock lock(mMutex);
648 
649     if (mAbandoned) {
650         GLC_LOGE("attachToContext: abandoned GLConsumer");
651         return NO_INIT;
652     }
653 
654     if (mAttached) {
655         GLC_LOGE("attachToContext: GLConsumer is already attached to a "
656                 "context");
657         return INVALID_OPERATION;
658     }
659 
660     EGLDisplay dpy = eglGetCurrentDisplay();
661     EGLContext ctx = eglGetCurrentContext();
662 
663     if (dpy == EGL_NO_DISPLAY) {
664         GLC_LOGE("attachToContext: invalid current EGLDisplay");
665         return INVALID_OPERATION;
666     }
667 
668     if (ctx == EGL_NO_CONTEXT) {
669         GLC_LOGE("attachToContext: invalid current EGLContext");
670         return INVALID_OPERATION;
671     }
672 
673     // We need to bind the texture regardless of whether there's a current
674     // buffer.
675     glBindTexture(mTexTarget, GLuint(tex));
676 
677     mEglDisplay = dpy;
678     mEglContext = ctx;
679     mTexName = tex;
680     mAttached = true;
681 
682     if (mCurrentTextureImage != NULL) {
683         // This may wait for a buffer a second time. This is likely required if
684         // this is a different context, since otherwise the wait could be skipped
685         // by bouncing through another context. For the same context the extra
686         // wait is redundant.
687         status_t err =  bindTextureImageLocked();
688         if (err != NO_ERROR) {
689             return err;
690         }
691     }
692 
693     return OK;
694 }
695 
696 
syncForReleaseLocked(EGLDisplay dpy)697 status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
698     GLC_LOGV("syncForReleaseLocked");
699 
700     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
701         if (SyncFeatures::getInstance().useNativeFenceSync()) {
702             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
703                     EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
704             if (sync == EGL_NO_SYNC_KHR) {
705                 GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
706                         eglGetError());
707                 return UNKNOWN_ERROR;
708             }
709             glFlush();
710             int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
711             eglDestroySyncKHR(dpy, sync);
712             if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
713                 GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
714                         "fd: %#x", eglGetError());
715                 return UNKNOWN_ERROR;
716             }
717             sp<Fence> fence(new Fence(fenceFd));
718             status_t err = addReleaseFenceLocked(mCurrentTexture,
719                     mCurrentTextureImage->graphicBuffer(), fence);
720             if (err != OK) {
721                 GLC_LOGE("syncForReleaseLocked: error adding release fence: "
722                         "%s (%d)", strerror(-err), err);
723                 return err;
724             }
725         } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
726             EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
727             if (fence != EGL_NO_SYNC_KHR) {
728                 // There is already a fence for the current slot.  We need to
729                 // wait on that before replacing it with another fence to
730                 // ensure that all outstanding buffer accesses have completed
731                 // before the producer accesses it.
732                 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
733                 if (result == EGL_FALSE) {
734                     GLC_LOGE("syncForReleaseLocked: error waiting for previous "
735                             "fence: %#x", eglGetError());
736                     return UNKNOWN_ERROR;
737                 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
738                     GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
739                             "fence");
740                     return TIMED_OUT;
741                 }
742                 eglDestroySyncKHR(dpy, fence);
743             }
744 
745             // Create a fence for the outstanding accesses in the current
746             // OpenGL ES context.
747             fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
748             if (fence == EGL_NO_SYNC_KHR) {
749                 GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
750                         eglGetError());
751                 return UNKNOWN_ERROR;
752             }
753             glFlush();
754             mEglSlots[mCurrentTexture].mEglFence = fence;
755         }
756     }
757 
758     return OK;
759 }
760 
isExternalFormat(PixelFormat format)761 bool GLConsumer::isExternalFormat(PixelFormat format)
762 {
763     switch (format) {
764     // supported YUV formats
765     case HAL_PIXEL_FORMAT_YV12:
766     // Legacy/deprecated YUV formats
767     case HAL_PIXEL_FORMAT_YCbCr_422_SP:
768     case HAL_PIXEL_FORMAT_YCrCb_420_SP:
769     case HAL_PIXEL_FORMAT_YCbCr_422_I:
770         return true;
771     }
772 
773     // Any OEM format needs to be considered
774     if (format>=0x100 && format<=0x1FF)
775         return true;
776 
777     return false;
778 }
779 
getCurrentTextureTarget() const780 uint32_t GLConsumer::getCurrentTextureTarget() const {
781     return mTexTarget;
782 }
783 
getTransformMatrix(float mtx[16])784 void GLConsumer::getTransformMatrix(float mtx[16]) {
785     Mutex::Autolock lock(mMutex);
786     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
787 }
788 
setFilteringEnabled(bool enabled)789 void GLConsumer::setFilteringEnabled(bool enabled) {
790     Mutex::Autolock lock(mMutex);
791     if (mAbandoned) {
792         GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
793         return;
794     }
795     bool needsRecompute = mFilteringEnabled != enabled;
796     mFilteringEnabled = enabled;
797 
798     if (needsRecompute && mCurrentTextureImage==NULL) {
799         GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
800     }
801 
802     if (needsRecompute && mCurrentTextureImage != NULL) {
803         computeCurrentTransformMatrixLocked();
804     }
805 }
806 
computeCurrentTransformMatrixLocked()807 void GLConsumer::computeCurrentTransformMatrixLocked() {
808     GLC_LOGV("computeCurrentTransformMatrixLocked");
809     sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
810             nullptr : mCurrentTextureImage->graphicBuffer();
811     if (buf == nullptr) {
812         GLC_LOGD("computeCurrentTransformMatrixLocked: "
813                 "mCurrentTextureImage is NULL");
814     }
815     computeTransformMatrix(mCurrentTransformMatrix, buf,
816         isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
817         mCurrentTransform, mFilteringEnabled);
818 }
819 
computeTransformMatrix(float outTransform[16],const sp<GraphicBuffer> & buf,const Rect & cropRect,uint32_t transform,bool filtering)820 void GLConsumer::computeTransformMatrix(float outTransform[16],
821         const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
822         bool filtering) {
823 
824     float xform[16];
825     for (int i = 0; i < 16; i++) {
826         xform[i] = mtxIdentity[i];
827     }
828     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
829         float result[16];
830         mtxMul(result, xform, mtxFlipH);
831         for (int i = 0; i < 16; i++) {
832             xform[i] = result[i];
833         }
834     }
835     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
836         float result[16];
837         mtxMul(result, xform, mtxFlipV);
838         for (int i = 0; i < 16; i++) {
839             xform[i] = result[i];
840         }
841     }
842     if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
843         float result[16];
844         mtxMul(result, xform, mtxRot90);
845         for (int i = 0; i < 16; i++) {
846             xform[i] = result[i];
847         }
848     }
849 
850     float mtxBeforeFlipV[16];
851     if (!cropRect.isEmpty()) {
852         float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
853         float bufferWidth = buf->getWidth();
854         float bufferHeight = buf->getHeight();
855         float shrinkAmount = 0.0f;
856         if (filtering) {
857             // In order to prevent bilinear sampling beyond the edge of the
858             // crop rectangle we may need to shrink it by 2 texels in each
859             // dimension.  Normally this would just need to take 1/2 a texel
860             // off each end, but because the chroma channels of YUV420 images
861             // are subsampled we may need to shrink the crop region by a whole
862             // texel on each side.
863             switch (buf->getPixelFormat()) {
864                 case PIXEL_FORMAT_RGBA_8888:
865                 case PIXEL_FORMAT_RGBX_8888:
866                 case PIXEL_FORMAT_RGBA_FP16:
867                 case PIXEL_FORMAT_RGBA_1010102:
868                 case PIXEL_FORMAT_RGB_888:
869                 case PIXEL_FORMAT_RGB_565:
870                 case PIXEL_FORMAT_BGRA_8888:
871                     // We know there's no subsampling of any channels, so we
872                     // only need to shrink by a half a pixel.
873                     shrinkAmount = 0.5;
874                     break;
875 
876                 default:
877                     // If we don't recognize the format, we must assume the
878                     // worst case (that we care about), which is YUV420.
879                     shrinkAmount = 1.0;
880                     break;
881             }
882         }
883 
884         // Only shrink the dimensions that are not the size of the buffer.
885         if (cropRect.width() < bufferWidth) {
886             tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
887             sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
888                     bufferWidth;
889         }
890         if (cropRect.height() < bufferHeight) {
891             ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
892                     bufferHeight;
893             sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
894                     bufferHeight;
895         }
896         float crop[16] = {
897             sx, 0, 0, 0,
898             0, sy, 0, 0,
899             0, 0, 1, 0,
900             tx, ty, 0, 1,
901         };
902 
903         mtxMul(mtxBeforeFlipV, crop, xform);
904     } else {
905         for (int i = 0; i < 16; i++) {
906             mtxBeforeFlipV[i] = xform[i];
907         }
908     }
909 
910     // SurfaceFlinger expects the top of its window textures to be at a Y
911     // coordinate of 0, so GLConsumer must behave the same way.  We don't
912     // want to expose this to applications, however, so we must add an
913     // additional vertical flip to the transform after all the other transforms.
914     mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
915 }
916 
getTimestamp()917 nsecs_t GLConsumer::getTimestamp() {
918     GLC_LOGV("getTimestamp");
919     Mutex::Autolock lock(mMutex);
920     return mCurrentTimestamp;
921 }
922 
getCurrentDataSpace()923 android_dataspace GLConsumer::getCurrentDataSpace() {
924     GLC_LOGV("getCurrentDataSpace");
925     Mutex::Autolock lock(mMutex);
926     return mCurrentDataSpace;
927 }
928 
getFrameNumber()929 uint64_t GLConsumer::getFrameNumber() {
930     GLC_LOGV("getFrameNumber");
931     Mutex::Autolock lock(mMutex);
932     return mCurrentFrameNumber;
933 }
934 
getCurrentBuffer(int * outSlot) const935 sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
936     Mutex::Autolock lock(mMutex);
937 
938     if (outSlot != nullptr) {
939         *outSlot = mCurrentTexture;
940     }
941 
942     return (mCurrentTextureImage == nullptr) ?
943             NULL : mCurrentTextureImage->graphicBuffer();
944 }
945 
getCurrentCrop() const946 Rect GLConsumer::getCurrentCrop() const {
947     Mutex::Autolock lock(mMutex);
948 
949     Rect outCrop = mCurrentCrop;
950     if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
951         uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
952         uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
953 
954         if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
955             newWidth = newHeight * mDefaultWidth / mDefaultHeight;
956             GLC_LOGV("too wide: newWidth = %d", newWidth);
957         } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
958             newHeight = newWidth * mDefaultHeight / mDefaultWidth;
959             GLC_LOGV("too tall: newHeight = %d", newHeight);
960         }
961 
962         uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
963         uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
964 
965         // The crop is too wide
966         if (newWidth < currentWidth) {
967             uint32_t dw = currentWidth - newWidth;
968             auto halfdw = dw / 2;
969             outCrop.left += halfdw;
970             // Not halfdw because it would subtract 1 too few when dw is odd
971             outCrop.right -= (dw - halfdw);
972         // The crop is too tall
973         } else if (newHeight < currentHeight) {
974             uint32_t dh = currentHeight - newHeight;
975             auto halfdh = dh / 2;
976             outCrop.top += halfdh;
977             // Not halfdh because it would subtract 1 too few when dh is odd
978             outCrop.bottom -= (dh - halfdh);
979         }
980 
981         GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
982             outCrop.left, outCrop.top,
983             outCrop.right,outCrop.bottom);
984     }
985 
986     return outCrop;
987 }
988 
getCurrentTransform() const989 uint32_t GLConsumer::getCurrentTransform() const {
990     Mutex::Autolock lock(mMutex);
991     return mCurrentTransform;
992 }
993 
getCurrentScalingMode() const994 uint32_t GLConsumer::getCurrentScalingMode() const {
995     Mutex::Autolock lock(mMutex);
996     return mCurrentScalingMode;
997 }
998 
getCurrentFence() const999 sp<Fence> GLConsumer::getCurrentFence() const {
1000     Mutex::Autolock lock(mMutex);
1001     return mCurrentFence;
1002 }
1003 
getCurrentFenceTime() const1004 std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
1005     Mutex::Autolock lock(mMutex);
1006     return mCurrentFenceTime;
1007 }
1008 
doGLFenceWait() const1009 status_t GLConsumer::doGLFenceWait() const {
1010     Mutex::Autolock lock(mMutex);
1011     return doGLFenceWaitLocked();
1012 }
1013 
doGLFenceWaitLocked() const1014 status_t GLConsumer::doGLFenceWaitLocked() const {
1015 
1016     EGLDisplay dpy = eglGetCurrentDisplay();
1017     EGLContext ctx = eglGetCurrentContext();
1018 
1019     if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
1020         GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
1021         return INVALID_OPERATION;
1022     }
1023 
1024     if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
1025         GLC_LOGE("doGLFenceWait: invalid current EGLContext");
1026         return INVALID_OPERATION;
1027     }
1028 
1029     if (mCurrentFence->isValid()) {
1030         if (SyncFeatures::getInstance().useWaitSync()) {
1031             // Create an EGLSyncKHR from the current fence.
1032             int fenceFd = mCurrentFence->dup();
1033             if (fenceFd == -1) {
1034                 GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
1035                 return -errno;
1036             }
1037             EGLint attribs[] = {
1038                 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
1039                 EGL_NONE
1040             };
1041             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
1042                     EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
1043             if (sync == EGL_NO_SYNC_KHR) {
1044                 close(fenceFd);
1045                 GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
1046                         eglGetError());
1047                 return UNKNOWN_ERROR;
1048             }
1049 
1050             // XXX: The spec draft is inconsistent as to whether this should
1051             // return an EGLint or void.  Ignore the return value for now, as
1052             // it's not strictly needed.
1053             eglWaitSyncKHR(dpy, sync, 0);
1054             EGLint eglErr = eglGetError();
1055             eglDestroySyncKHR(dpy, sync);
1056             if (eglErr != EGL_SUCCESS) {
1057                 GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
1058                         eglErr);
1059                 return UNKNOWN_ERROR;
1060             }
1061         } else {
1062             status_t err = mCurrentFence->waitForever(
1063                     "GLConsumer::doGLFenceWaitLocked");
1064             if (err != NO_ERROR) {
1065                 GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
1066                 return err;
1067             }
1068         }
1069     }
1070 
1071     return NO_ERROR;
1072 }
1073 
freeBufferLocked(int slotIndex)1074 void GLConsumer::freeBufferLocked(int slotIndex) {
1075     GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
1076     if (slotIndex == mCurrentTexture) {
1077         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
1078     }
1079     mEglSlots[slotIndex].mEglImage.clear();
1080     ConsumerBase::freeBufferLocked(slotIndex);
1081 }
1082 
abandonLocked()1083 void GLConsumer::abandonLocked() {
1084     GLC_LOGV("abandonLocked");
1085     mCurrentTextureImage.clear();
1086     ConsumerBase::abandonLocked();
1087 }
1088 
setName(const String8 & name)1089 void GLConsumer::setName(const String8& name) {
1090     Mutex::Autolock _l(mMutex);
1091     if (mAbandoned) {
1092         GLC_LOGE("setName: GLConsumer is abandoned!");
1093         return;
1094     }
1095     mName = name;
1096     mConsumer->setConsumerName(name);
1097 }
1098 
setDefaultBufferFormat(PixelFormat defaultFormat)1099 status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
1100     Mutex::Autolock lock(mMutex);
1101     if (mAbandoned) {
1102         GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
1103         return NO_INIT;
1104     }
1105     return mConsumer->setDefaultBufferFormat(defaultFormat);
1106 }
1107 
setDefaultBufferDataSpace(android_dataspace defaultDataSpace)1108 status_t GLConsumer::setDefaultBufferDataSpace(
1109         android_dataspace defaultDataSpace) {
1110     Mutex::Autolock lock(mMutex);
1111     if (mAbandoned) {
1112         GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
1113         return NO_INIT;
1114     }
1115     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
1116 }
1117 
setConsumerUsageBits(uint64_t usage)1118 status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
1119     Mutex::Autolock lock(mMutex);
1120     if (mAbandoned) {
1121         GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
1122         return NO_INIT;
1123     }
1124     usage |= DEFAULT_USAGE_FLAGS;
1125     return mConsumer->setConsumerUsageBits(usage);
1126 }
1127 
setTransformHint(uint32_t hint)1128 status_t GLConsumer::setTransformHint(uint32_t hint) {
1129     Mutex::Autolock lock(mMutex);
1130     if (mAbandoned) {
1131         GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
1132         return NO_INIT;
1133     }
1134     return mConsumer->setTransformHint(hint);
1135 }
1136 
setMaxAcquiredBufferCount(int maxAcquiredBuffers)1137 status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
1138     Mutex::Autolock lock(mMutex);
1139     if (mAbandoned) {
1140         GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
1141         return NO_INIT;
1142     }
1143     return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
1144 }
1145 
dumpLocked(String8 & result,const char * prefix) const1146 void GLConsumer::dumpLocked(String8& result, const char* prefix) const
1147 {
1148     result.appendFormat(
1149        "%smTexName=%d mCurrentTexture=%d\n"
1150        "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
1151        prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
1152        mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
1153        mCurrentTransform);
1154 
1155     ConsumerBase::dumpLocked(result, prefix);
1156 }
1157 
mtxMul(float out[16],const float a[16],const float b[16])1158 static void mtxMul(float out[16], const float a[16], const float b[16]) {
1159     out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1160     out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1161     out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1162     out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1163 
1164     out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1165     out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1166     out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1167     out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1168 
1169     out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1170     out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1171     out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1172     out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1173 
1174     out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1175     out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1176     out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1177     out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1178 }
1179 
EglImage(sp<GraphicBuffer> graphicBuffer)1180 GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
1181     mGraphicBuffer(graphicBuffer),
1182     mEglImage(EGL_NO_IMAGE_KHR),
1183     mEglDisplay(EGL_NO_DISPLAY),
1184     mCropRect(Rect::EMPTY_RECT) {
1185 }
1186 
~EglImage()1187 GLConsumer::EglImage::~EglImage() {
1188     if (mEglImage != EGL_NO_IMAGE_KHR) {
1189         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1190            ALOGE("~EglImage: eglDestroyImageKHR failed");
1191         }
1192         eglTerminate(mEglDisplay);
1193     }
1194 }
1195 
createIfNeeded(EGLDisplay eglDisplay,const Rect & cropRect,bool forceCreation)1196 status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
1197                                               const Rect& cropRect,
1198                                               bool forceCreation) {
1199     // If there's an image and it's no longer valid, destroy it.
1200     bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
1201     bool displayInvalid = mEglDisplay != eglDisplay;
1202     bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
1203     if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
1204         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1205            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
1206         }
1207         eglTerminate(mEglDisplay);
1208         mEglImage = EGL_NO_IMAGE_KHR;
1209         mEglDisplay = EGL_NO_DISPLAY;
1210     }
1211 
1212     // If there's no image, create one.
1213     if (mEglImage == EGL_NO_IMAGE_KHR) {
1214         mEglDisplay = eglDisplay;
1215         mCropRect = cropRect;
1216         mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
1217     }
1218 
1219     // Fail if we can't create a valid image.
1220     if (mEglImage == EGL_NO_IMAGE_KHR) {
1221         mEglDisplay = EGL_NO_DISPLAY;
1222         mCropRect.makeInvalid();
1223         const sp<GraphicBuffer>& buffer = mGraphicBuffer;
1224         ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
1225             buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
1226             buffer->getUsage(), buffer->getPixelFormat());
1227         return UNKNOWN_ERROR;
1228     }
1229 
1230     return OK;
1231 }
1232 
bindToTextureTarget(uint32_t texTarget)1233 void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1234     glEGLImageTargetTexture2DOES(texTarget,
1235             static_cast<GLeglImageOES>(mEglImage));
1236 }
1237 
createImage(EGLDisplay dpy,const sp<GraphicBuffer> & graphicBuffer,const Rect & crop)1238 EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
1239         const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
1240     EGLClientBuffer cbuf =
1241             static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1242     const bool createProtectedImage =
1243             (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
1244             hasEglProtectedContent();
1245     EGLint attrs[] = {
1246         EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
1247         EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
1248         EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
1249         EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
1250         EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
1251         createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1252         createProtectedImage ? EGL_TRUE : EGL_NONE,
1253         EGL_NONE,
1254     };
1255     if (!crop.isValid()) {
1256         // No crop rect to set, so leave the crop out of the attrib array. Make
1257         // sure to propagate the protected content attrs if they are set.
1258         attrs[2] = attrs[10];
1259         attrs[3] = attrs[11];
1260         attrs[4] = EGL_NONE;
1261     } else if (!isEglImageCroppable(crop)) {
1262         // The crop rect is not at the origin, so we can't set the crop on the
1263         // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
1264         // extension.  In the future we can add a layered extension that
1265         // removes this restriction if there is hardware that can support it.
1266         attrs[2] = attrs[10];
1267         attrs[3] = attrs[11];
1268         attrs[4] = EGL_NONE;
1269     }
1270     eglInitialize(dpy, 0, 0);
1271     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
1272             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
1273     if (image == EGL_NO_IMAGE_KHR) {
1274         EGLint error = eglGetError();
1275         ALOGE("error creating EGLImage: %#x", error);
1276         eglTerminate(dpy);
1277     }
1278     return image;
1279 }
1280 
1281 }; // namespace android
1282