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