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        uint32_t* bits;
350        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
351        uint32_t stride = buffer->getStride();
352        uint32_t height = buffer->getHeight();
353        memset(bits, 0, stride * height * 4);
354        for (uint32_t y = 0; y < kDebugData.height; y++) {
355            for (uint32_t x = 0; x < kDebugData.width; x++) {
356                bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
357                    0xFF000000 : 0xFFFFFFFF;
358            }
359            bits += stride;
360        }
361        buffer->unlock();
362        sReleasedTexImageBuffer = buffer;
363    }
364    return sReleasedTexImageBuffer;
365}
366
367status_t GLConsumer::acquireBufferLocked(BufferItem *item,
368        nsecs_t presentWhen, uint64_t maxFrameNumber) {
369    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
370            maxFrameNumber);
371    if (err != NO_ERROR) {
372        return err;
373    }
374
375    // If item->mGraphicBuffer is not null, this buffer has not been acquired
376    // before, so any prior EglImage created is using a stale buffer. This
377    // replaces any old EglImage with a new one (using the new buffer).
378    if (item->mGraphicBuffer != NULL) {
379        int slot = item->mSlot;
380        mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
381    }
382
383    return NO_ERROR;
384}
385
386status_t GLConsumer::releaseBufferLocked(int buf,
387        sp<GraphicBuffer> graphicBuffer,
388        EGLDisplay display, EGLSyncKHR eglFence) {
389    // release the buffer if it hasn't already been discarded by the
390    // BufferQueue. This can happen, for example, when the producer of this
391    // buffer has reallocated the original buffer slot after this buffer
392    // was acquired.
393    status_t err = ConsumerBase::releaseBufferLocked(
394            buf, graphicBuffer, display, eglFence);
395    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
396    return err;
397}
398
399status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
400        PendingRelease* pendingRelease)
401{
402    status_t err = NO_ERROR;
403
404    int slot = item.mSlot;
405
406    if (!mAttached) {
407        GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
408                "ES context");
409        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
410                mEglDisplay, EGL_NO_SYNC_KHR);
411        return INVALID_OPERATION;
412    }
413
414    // Confirm state.
415    err = checkAndUpdateEglStateLocked();
416    if (err != NO_ERROR) {
417        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
418                mEglDisplay, EGL_NO_SYNC_KHR);
419        return err;
420    }
421
422    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
423    // if nessessary, for the gralloc buffer currently in the slot in
424    // ConsumerBase.
425    // We may have to do this even when item.mGraphicBuffer == NULL (which
426    // means the buffer was previously acquired).
427    err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
428    if (err != NO_ERROR) {
429        GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
430                mEglDisplay, slot);
431        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
432                mEglDisplay, EGL_NO_SYNC_KHR);
433        return UNKNOWN_ERROR;
434    }
435
436    // Do whatever sync ops we need to do before releasing the old slot.
437    if (slot != mCurrentTexture) {
438        err = syncForReleaseLocked(mEglDisplay);
439        if (err != NO_ERROR) {
440            // Release the buffer we just acquired.  It's not safe to
441            // release the old buffer, so instead we just drop the new frame.
442            // As we are still under lock since acquireBuffer, it is safe to
443            // release by slot.
444            releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
445                    mEglDisplay, EGL_NO_SYNC_KHR);
446            return err;
447        }
448    }
449
450    GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
451            mCurrentTexture, mCurrentTextureImage != NULL ?
452                    mCurrentTextureImage->graphicBufferHandle() : 0,
453            slot, mSlots[slot].mGraphicBuffer->handle);
454
455    // Hang onto the pointer so that it isn't freed in the call to
456    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
457    // the same.
458    sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
459
460    // release old buffer
461    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
462        if (pendingRelease == nullptr) {
463            status_t status = releaseBufferLocked(
464                    mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
465                    mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
466            if (status < NO_ERROR) {
467                GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
468                        strerror(-status), status);
469                err = status;
470                // keep going, with error raised [?]
471            }
472        } else {
473            pendingRelease->currentTexture = mCurrentTexture;
474            pendingRelease->graphicBuffer =
475                    mCurrentTextureImage->graphicBuffer();
476            pendingRelease->display = mEglDisplay;
477            pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
478            pendingRelease->isPending = true;
479        }
480    }
481
482    // Update the GLConsumer state.
483    mCurrentTexture = slot;
484    mCurrentTextureImage = nextTextureImage;
485    mCurrentCrop = item.mCrop;
486    mCurrentTransform = item.mTransform;
487    mCurrentScalingMode = item.mScalingMode;
488    mCurrentTimestamp = item.mTimestamp;
489    mCurrentFence = item.mFence;
490    mCurrentFrameNumber = item.mFrameNumber;
491
492    computeCurrentTransformMatrixLocked();
493
494    return err;
495}
496
497status_t GLConsumer::bindTextureImageLocked() {
498    if (mEglDisplay == EGL_NO_DISPLAY) {
499        ALOGE("bindTextureImage: invalid display");
500        return INVALID_OPERATION;
501    }
502
503    GLenum error;
504    while ((error = glGetError()) != GL_NO_ERROR) {
505        GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
506    }
507
508    glBindTexture(mTexTarget, mTexName);
509    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
510            mCurrentTextureImage == NULL) {
511        GLC_LOGE("bindTextureImage: no currently-bound texture");
512        return NO_INIT;
513    }
514
515    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
516                                                        mCurrentCrop);
517    if (err != NO_ERROR) {
518        GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
519                mEglDisplay, mCurrentTexture);
520        return UNKNOWN_ERROR;
521    }
522    mCurrentTextureImage->bindToTextureTarget(mTexTarget);
523
524    // In the rare case that the display is terminated and then initialized
525    // again, we can't detect that the display changed (it didn't), but the
526    // image is invalid. In this case, repeat the exact same steps while
527    // forcing the creation of a new image.
528    if ((error = glGetError()) != GL_NO_ERROR) {
529        glBindTexture(mTexTarget, mTexName);
530        status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay,
531                                                               mCurrentCrop,
532                                                               true);
533        if (result != NO_ERROR) {
534            GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
535                    mEglDisplay, mCurrentTexture);
536            return UNKNOWN_ERROR;
537        }
538        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
539        if ((error = glGetError()) != GL_NO_ERROR) {
540            GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
541            return UNKNOWN_ERROR;
542        }
543    }
544
545    // Wait for the new buffer to be ready.
546    return doGLFenceWaitLocked();
547}
548
549status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
550    EGLDisplay dpy = eglGetCurrentDisplay();
551    EGLContext ctx = eglGetCurrentContext();
552
553    if (!contextCheck) {
554        // if this is the first time we're called, mEglDisplay/mEglContext have
555        // never been set, so don't error out (below).
556        if (mEglDisplay == EGL_NO_DISPLAY) {
557            mEglDisplay = dpy;
558        }
559        if (mEglContext == EGL_NO_CONTEXT) {
560            mEglContext = ctx;
561        }
562    }
563
564    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
565        GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
566        return INVALID_OPERATION;
567    }
568
569    if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
570        GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
571        return INVALID_OPERATION;
572    }
573
574    mEglDisplay = dpy;
575    mEglContext = ctx;
576    return NO_ERROR;
577}
578
579void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
580    if (fence->isValid() &&
581            mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
582        status_t err = addReleaseFence(mCurrentTexture,
583                mCurrentTextureImage->graphicBuffer(), fence);
584        if (err != OK) {
585            GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
586                    strerror(-err), err);
587        }
588    }
589}
590
591status_t GLConsumer::detachFromContext() {
592    ATRACE_CALL();
593    GLC_LOGV("detachFromContext");
594    Mutex::Autolock lock(mMutex);
595
596    if (mAbandoned) {
597        GLC_LOGE("detachFromContext: abandoned GLConsumer");
598        return NO_INIT;
599    }
600
601    if (!mAttached) {
602        GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
603                "context");
604        return INVALID_OPERATION;
605    }
606
607    EGLDisplay dpy = eglGetCurrentDisplay();
608    EGLContext ctx = eglGetCurrentContext();
609
610    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
611        GLC_LOGE("detachFromContext: invalid current EGLDisplay");
612        return INVALID_OPERATION;
613    }
614
615    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
616        GLC_LOGE("detachFromContext: invalid current EGLContext");
617        return INVALID_OPERATION;
618    }
619
620    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
621        status_t err = syncForReleaseLocked(dpy);
622        if (err != OK) {
623            return err;
624        }
625
626        glDeleteTextures(1, &mTexName);
627    }
628
629    mEglDisplay = EGL_NO_DISPLAY;
630    mEglContext = EGL_NO_CONTEXT;
631    mAttached = false;
632
633    return OK;
634}
635
636status_t GLConsumer::attachToContext(uint32_t tex) {
637    ATRACE_CALL();
638    GLC_LOGV("attachToContext");
639    Mutex::Autolock lock(mMutex);
640
641    if (mAbandoned) {
642        GLC_LOGE("attachToContext: abandoned GLConsumer");
643        return NO_INIT;
644    }
645
646    if (mAttached) {
647        GLC_LOGE("attachToContext: GLConsumer is already attached to a "
648                "context");
649        return INVALID_OPERATION;
650    }
651
652    EGLDisplay dpy = eglGetCurrentDisplay();
653    EGLContext ctx = eglGetCurrentContext();
654
655    if (dpy == EGL_NO_DISPLAY) {
656        GLC_LOGE("attachToContext: invalid current EGLDisplay");
657        return INVALID_OPERATION;
658    }
659
660    if (ctx == EGL_NO_CONTEXT) {
661        GLC_LOGE("attachToContext: invalid current EGLContext");
662        return INVALID_OPERATION;
663    }
664
665    // We need to bind the texture regardless of whether there's a current
666    // buffer.
667    glBindTexture(mTexTarget, GLuint(tex));
668
669    mEglDisplay = dpy;
670    mEglContext = ctx;
671    mTexName = tex;
672    mAttached = true;
673
674    if (mCurrentTextureImage != NULL) {
675        // This may wait for a buffer a second time. This is likely required if
676        // this is a different context, since otherwise the wait could be skipped
677        // by bouncing through another context. For the same context the extra
678        // wait is redundant.
679        status_t err =  bindTextureImageLocked();
680        if (err != NO_ERROR) {
681            return err;
682        }
683    }
684
685    return OK;
686}
687
688
689status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
690    GLC_LOGV("syncForReleaseLocked");
691
692    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
693        if (SyncFeatures::getInstance().useNativeFenceSync()) {
694            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
695                    EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
696            if (sync == EGL_NO_SYNC_KHR) {
697                GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
698                        eglGetError());
699                return UNKNOWN_ERROR;
700            }
701            glFlush();
702            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
703            eglDestroySyncKHR(dpy, sync);
704            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
705                GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
706                        "fd: %#x", eglGetError());
707                return UNKNOWN_ERROR;
708            }
709            sp<Fence> fence(new Fence(fenceFd));
710            status_t err = addReleaseFenceLocked(mCurrentTexture,
711                    mCurrentTextureImage->graphicBuffer(), fence);
712            if (err != OK) {
713                GLC_LOGE("syncForReleaseLocked: error adding release fence: "
714                        "%s (%d)", strerror(-err), err);
715                return err;
716            }
717        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
718            EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
719            if (fence != EGL_NO_SYNC_KHR) {
720                // There is already a fence for the current slot.  We need to
721                // wait on that before replacing it with another fence to
722                // ensure that all outstanding buffer accesses have completed
723                // before the producer accesses it.
724                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
725                if (result == EGL_FALSE) {
726                    GLC_LOGE("syncForReleaseLocked: error waiting for previous "
727                            "fence: %#x", eglGetError());
728                    return UNKNOWN_ERROR;
729                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
730                    GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
731                            "fence");
732                    return TIMED_OUT;
733                }
734                eglDestroySyncKHR(dpy, fence);
735            }
736
737            // Create a fence for the outstanding accesses in the current
738            // OpenGL ES context.
739            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
740            if (fence == EGL_NO_SYNC_KHR) {
741                GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
742                        eglGetError());
743                return UNKNOWN_ERROR;
744            }
745            glFlush();
746            mEglSlots[mCurrentTexture].mEglFence = fence;
747        }
748    }
749
750    return OK;
751}
752
753bool GLConsumer::isExternalFormat(PixelFormat format)
754{
755    switch (format) {
756    // supported YUV formats
757    case HAL_PIXEL_FORMAT_YV12:
758    // Legacy/deprecated YUV formats
759    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
760    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
761    case HAL_PIXEL_FORMAT_YCbCr_422_I:
762        return true;
763    }
764
765    // Any OEM format needs to be considered
766    if (format>=0x100 && format<=0x1FF)
767        return true;
768
769    return false;
770}
771
772uint32_t GLConsumer::getCurrentTextureTarget() const {
773    return mTexTarget;
774}
775
776void GLConsumer::getTransformMatrix(float mtx[16]) {
777    Mutex::Autolock lock(mMutex);
778    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
779}
780
781void GLConsumer::setFilteringEnabled(bool enabled) {
782    Mutex::Autolock lock(mMutex);
783    if (mAbandoned) {
784        GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
785        return;
786    }
787    bool needsRecompute = mFilteringEnabled != enabled;
788    mFilteringEnabled = enabled;
789
790    if (needsRecompute && mCurrentTextureImage==NULL) {
791        GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
792    }
793
794    if (needsRecompute && mCurrentTextureImage != NULL) {
795        computeCurrentTransformMatrixLocked();
796    }
797}
798
799void GLConsumer::computeCurrentTransformMatrixLocked() {
800    GLC_LOGV("computeCurrentTransformMatrixLocked");
801    sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
802            nullptr : mCurrentTextureImage->graphicBuffer();
803    if (buf == nullptr) {
804        GLC_LOGD("computeCurrentTransformMatrixLocked: "
805                "mCurrentTextureImage is NULL");
806    }
807    computeTransformMatrix(mCurrentTransformMatrix, buf,
808        isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
809        mCurrentTransform, mFilteringEnabled);
810}
811
812void GLConsumer::computeTransformMatrix(float outTransform[16],
813        const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
814        bool filtering) {
815
816    float xform[16];
817    for (int i = 0; i < 16; i++) {
818        xform[i] = mtxIdentity[i];
819    }
820    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
821        float result[16];
822        mtxMul(result, xform, mtxFlipH);
823        for (int i = 0; i < 16; i++) {
824            xform[i] = result[i];
825        }
826    }
827    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
828        float result[16];
829        mtxMul(result, xform, mtxFlipV);
830        for (int i = 0; i < 16; i++) {
831            xform[i] = result[i];
832        }
833    }
834    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
835        float result[16];
836        mtxMul(result, xform, mtxRot90);
837        for (int i = 0; i < 16; i++) {
838            xform[i] = result[i];
839        }
840    }
841
842    float mtxBeforeFlipV[16];
843    if (!cropRect.isEmpty()) {
844        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
845        float bufferWidth = buf->getWidth();
846        float bufferHeight = buf->getHeight();
847        float shrinkAmount = 0.0f;
848        if (filtering) {
849            // In order to prevent bilinear sampling beyond the edge of the
850            // crop rectangle we may need to shrink it by 2 texels in each
851            // dimension.  Normally this would just need to take 1/2 a texel
852            // off each end, but because the chroma channels of YUV420 images
853            // are subsampled we may need to shrink the crop region by a whole
854            // texel on each side.
855            switch (buf->getPixelFormat()) {
856                case PIXEL_FORMAT_RGBA_8888:
857                case PIXEL_FORMAT_RGBX_8888:
858                case PIXEL_FORMAT_RGB_888:
859                case PIXEL_FORMAT_RGB_565:
860                case PIXEL_FORMAT_BGRA_8888:
861                    // We know there's no subsampling of any channels, so we
862                    // only need to shrink by a half a pixel.
863                    shrinkAmount = 0.5;
864                    break;
865
866                default:
867                    // If we don't recognize the format, we must assume the
868                    // worst case (that we care about), which is YUV420.
869                    shrinkAmount = 1.0;
870                    break;
871            }
872        }
873
874        // Only shrink the dimensions that are not the size of the buffer.
875        if (cropRect.width() < bufferWidth) {
876            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
877            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
878                    bufferWidth;
879        }
880        if (cropRect.height() < bufferHeight) {
881            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
882                    bufferHeight;
883            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
884                    bufferHeight;
885        }
886        float crop[16] = {
887            sx, 0, 0, 0,
888            0, sy, 0, 0,
889            0, 0, 1, 0,
890            tx, ty, 0, 1,
891        };
892
893        mtxMul(mtxBeforeFlipV, crop, xform);
894    } else {
895        for (int i = 0; i < 16; i++) {
896            mtxBeforeFlipV[i] = xform[i];
897        }
898    }
899
900    // SurfaceFlinger expects the top of its window textures to be at a Y
901    // coordinate of 0, so GLConsumer must behave the same way.  We don't
902    // want to expose this to applications, however, so we must add an
903    // additional vertical flip to the transform after all the other transforms.
904    mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
905}
906
907nsecs_t GLConsumer::getTimestamp() {
908    GLC_LOGV("getTimestamp");
909    Mutex::Autolock lock(mMutex);
910    return mCurrentTimestamp;
911}
912
913uint64_t GLConsumer::getFrameNumber() {
914    GLC_LOGV("getFrameNumber");
915    Mutex::Autolock lock(mMutex);
916    return mCurrentFrameNumber;
917}
918
919sp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
920    Mutex::Autolock lock(mMutex);
921    return (mCurrentTextureImage == NULL) ?
922            NULL : mCurrentTextureImage->graphicBuffer();
923}
924
925Rect GLConsumer::getCurrentCrop() const {
926    Mutex::Autolock lock(mMutex);
927
928    Rect outCrop = mCurrentCrop;
929    if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
930        uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
931        uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
932
933        if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
934            newWidth = newHeight * mDefaultWidth / mDefaultHeight;
935            GLC_LOGV("too wide: newWidth = %d", newWidth);
936        } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
937            newHeight = newWidth * mDefaultHeight / mDefaultWidth;
938            GLC_LOGV("too tall: newHeight = %d", newHeight);
939        }
940
941        uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
942        uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
943
944        // The crop is too wide
945        if (newWidth < currentWidth) {
946            uint32_t dw = currentWidth - newWidth;
947            auto halfdw = dw / 2;
948            outCrop.left += halfdw;
949            // Not halfdw because it would subtract 1 too few when dw is odd
950            outCrop.right -= (dw - halfdw);
951        // The crop is too tall
952        } else if (newHeight < currentHeight) {
953            uint32_t dh = currentHeight - newHeight;
954            auto halfdh = dh / 2;
955            outCrop.top += halfdh;
956            // Not halfdh because it would subtract 1 too few when dh is odd
957            outCrop.bottom -= (dh - halfdh);
958        }
959
960        GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
961            outCrop.left, outCrop.top,
962            outCrop.right,outCrop.bottom);
963    }
964
965    return outCrop;
966}
967
968uint32_t GLConsumer::getCurrentTransform() const {
969    Mutex::Autolock lock(mMutex);
970    return mCurrentTransform;
971}
972
973uint32_t GLConsumer::getCurrentScalingMode() const {
974    Mutex::Autolock lock(mMutex);
975    return mCurrentScalingMode;
976}
977
978sp<Fence> GLConsumer::getCurrentFence() const {
979    Mutex::Autolock lock(mMutex);
980    return mCurrentFence;
981}
982
983status_t GLConsumer::doGLFenceWait() const {
984    Mutex::Autolock lock(mMutex);
985    return doGLFenceWaitLocked();
986}
987
988status_t GLConsumer::doGLFenceWaitLocked() const {
989
990    EGLDisplay dpy = eglGetCurrentDisplay();
991    EGLContext ctx = eglGetCurrentContext();
992
993    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
994        GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
995        return INVALID_OPERATION;
996    }
997
998    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
999        GLC_LOGE("doGLFenceWait: invalid current EGLContext");
1000        return INVALID_OPERATION;
1001    }
1002
1003    if (mCurrentFence->isValid()) {
1004        if (SyncFeatures::getInstance().useWaitSync()) {
1005            // Create an EGLSyncKHR from the current fence.
1006            int fenceFd = mCurrentFence->dup();
1007            if (fenceFd == -1) {
1008                GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
1009                return -errno;
1010            }
1011            EGLint attribs[] = {
1012                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
1013                EGL_NONE
1014            };
1015            EGLSyncKHR sync = eglCreateSyncKHR(dpy,
1016                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
1017            if (sync == EGL_NO_SYNC_KHR) {
1018                close(fenceFd);
1019                GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
1020                        eglGetError());
1021                return UNKNOWN_ERROR;
1022            }
1023
1024            // XXX: The spec draft is inconsistent as to whether this should
1025            // return an EGLint or void.  Ignore the return value for now, as
1026            // it's not strictly needed.
1027            eglWaitSyncKHR(dpy, sync, 0);
1028            EGLint eglErr = eglGetError();
1029            eglDestroySyncKHR(dpy, sync);
1030            if (eglErr != EGL_SUCCESS) {
1031                GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
1032                        eglErr);
1033                return UNKNOWN_ERROR;
1034            }
1035        } else {
1036            status_t err = mCurrentFence->waitForever(
1037                    "GLConsumer::doGLFenceWaitLocked");
1038            if (err != NO_ERROR) {
1039                GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
1040                return err;
1041            }
1042        }
1043    }
1044
1045    return NO_ERROR;
1046}
1047
1048void GLConsumer::freeBufferLocked(int slotIndex) {
1049    GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
1050    if (slotIndex == mCurrentTexture) {
1051        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
1052    }
1053    mEglSlots[slotIndex].mEglImage.clear();
1054    ConsumerBase::freeBufferLocked(slotIndex);
1055}
1056
1057void GLConsumer::abandonLocked() {
1058    GLC_LOGV("abandonLocked");
1059    mCurrentTextureImage.clear();
1060    ConsumerBase::abandonLocked();
1061}
1062
1063void GLConsumer::setName(const String8& name) {
1064    Mutex::Autolock _l(mMutex);
1065    if (mAbandoned) {
1066        GLC_LOGE("setName: GLConsumer is abandoned!");
1067        return;
1068    }
1069    mName = name;
1070    mConsumer->setConsumerName(name);
1071}
1072
1073status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
1074    Mutex::Autolock lock(mMutex);
1075    if (mAbandoned) {
1076        GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
1077        return NO_INIT;
1078    }
1079    return mConsumer->setDefaultBufferFormat(defaultFormat);
1080}
1081
1082status_t GLConsumer::setDefaultBufferDataSpace(
1083        android_dataspace defaultDataSpace) {
1084    Mutex::Autolock lock(mMutex);
1085    if (mAbandoned) {
1086        GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
1087        return NO_INIT;
1088    }
1089    return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
1090}
1091
1092status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
1093    Mutex::Autolock lock(mMutex);
1094    if (mAbandoned) {
1095        GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
1096        return NO_INIT;
1097    }
1098    usage |= DEFAULT_USAGE_FLAGS;
1099    return mConsumer->setConsumerUsageBits(usage);
1100}
1101
1102status_t GLConsumer::setTransformHint(uint32_t hint) {
1103    Mutex::Autolock lock(mMutex);
1104    if (mAbandoned) {
1105        GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
1106        return NO_INIT;
1107    }
1108    return mConsumer->setTransformHint(hint);
1109}
1110
1111status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
1112    Mutex::Autolock lock(mMutex);
1113    if (mAbandoned) {
1114        GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
1115        return NO_INIT;
1116    }
1117    return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
1118}
1119
1120void GLConsumer::dumpLocked(String8& result, const char* prefix) const
1121{
1122    result.appendFormat(
1123       "%smTexName=%d mCurrentTexture=%d\n"
1124       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
1125       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
1126       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
1127       mCurrentTransform);
1128
1129    ConsumerBase::dumpLocked(result, prefix);
1130}
1131
1132static void mtxMul(float out[16], const float a[16], const float b[16]) {
1133    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1134    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1135    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1136    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1137
1138    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1139    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1140    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1141    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1142
1143    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1144    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1145    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1146    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1147
1148    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1149    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1150    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1151    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1152}
1153
1154GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
1155    mGraphicBuffer(graphicBuffer),
1156    mEglImage(EGL_NO_IMAGE_KHR),
1157    mEglDisplay(EGL_NO_DISPLAY),
1158    mCropRect(Rect::EMPTY_RECT) {
1159}
1160
1161GLConsumer::EglImage::~EglImage() {
1162    if (mEglImage != EGL_NO_IMAGE_KHR) {
1163        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1164           ALOGE("~EglImage: eglDestroyImageKHR failed");
1165        }
1166        eglTerminate(mEglDisplay);
1167    }
1168}
1169
1170status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
1171                                              const Rect& cropRect,
1172                                              bool forceCreation) {
1173    // If there's an image and it's no longer valid, destroy it.
1174    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
1175    bool displayInvalid = mEglDisplay != eglDisplay;
1176    bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
1177    if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
1178        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1179           ALOGE("createIfNeeded: eglDestroyImageKHR failed");
1180        }
1181        eglTerminate(mEglDisplay);
1182        mEglImage = EGL_NO_IMAGE_KHR;
1183        mEglDisplay = EGL_NO_DISPLAY;
1184    }
1185
1186    // If there's no image, create one.
1187    if (mEglImage == EGL_NO_IMAGE_KHR) {
1188        mEglDisplay = eglDisplay;
1189        mCropRect = cropRect;
1190        mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
1191    }
1192
1193    // Fail if we can't create a valid image.
1194    if (mEglImage == EGL_NO_IMAGE_KHR) {
1195        mEglDisplay = EGL_NO_DISPLAY;
1196        mCropRect.makeInvalid();
1197        const sp<GraphicBuffer>& buffer = mGraphicBuffer;
1198        ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
1199            buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
1200            buffer->getUsage(), buffer->getPixelFormat());
1201        return UNKNOWN_ERROR;
1202    }
1203
1204    return OK;
1205}
1206
1207void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1208    glEGLImageTargetTexture2DOES(texTarget,
1209            static_cast<GLeglImageOES>(mEglImage));
1210}
1211
1212EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
1213        const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
1214    EGLClientBuffer cbuf =
1215            static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1216    const bool createProtectedImage =
1217            (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
1218            hasEglProtectedContent();
1219    EGLint attrs[] = {
1220        EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
1221        EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
1222        EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
1223        EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
1224        EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
1225        createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1226        createProtectedImage ? EGL_TRUE : EGL_NONE,
1227        EGL_NONE,
1228    };
1229    if (!crop.isValid()) {
1230        // No crop rect to set, so terminate the attrib array before the crop.
1231        attrs[2] = EGL_NONE;
1232    } else if (!isEglImageCroppable(crop)) {
1233        // The crop rect is not at the origin, so we can't set the crop on the
1234        // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
1235        // extension.  In the future we can add a layered extension that
1236        // removes this restriction if there is hardware that can support it.
1237        attrs[2] = EGL_NONE;
1238    }
1239    eglInitialize(dpy, 0, 0);
1240    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
1241            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
1242    if (image == EGL_NO_IMAGE_KHR) {
1243        EGLint error = eglGetError();
1244        ALOGE("error creating EGLImage: %#x", error);
1245        eglTerminate(dpy);
1246    }
1247    return image;
1248}
1249
1250}; // namespace android
1251