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