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