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