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