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