1e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/*
2376b1529a383c39adf4674baf6db83a5e63f97acJason Evans * Copyright (C) 2010 The Android Open Source Project
3e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *
4e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Licensed under the Apache License, Version 2.0 (the "License");
5e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * you may not use this file except in compliance with the License.
6e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * You may obtain a copy of the License at
7609ae595f0358157b19311b0f9f9591db7cee705Jason Evans *
8609ae595f0358157b19311b0f9f9591db7cee705Jason Evans *      http://www.apache.org/licenses/LICENSE-2.0
9e476f8a161d445211fd6e54fe370275196e66bcbJason Evans *
103c2343518c2b1fbbd66065c75a3c19f908de1d78Jason Evans * Unless required by applicable law or agreed to in writing, software
11e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * distributed under the License is distributed on an "AS IS" BASIS,
12e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans * See the License for the specific language governing permissions and
147ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans * limitations under the License.
157ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans */
167ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
177ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define LOG_TAG "GLConsumer"
187ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19609ae595f0358157b19311b0f9f9591db7cee705Jason Evans//#define LOG_NDEBUG 0
20609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
21609ae595f0358157b19311b0f9f9591db7cee705Jason Evans#define GL_GLEXT_PROTOTYPES
22609ae595f0358157b19311b0f9f9591db7cee705Jason Evans#define EGL_EGLEXT_PROTOTYPES
237ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
242dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#include <EGL/egl.h>
252dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#include <EGL/eglext.h>
26e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <GLES2/gl2.h>
27e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <GLES2/gl2ext.h>
28e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <cutils/compiler.h>
29e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
307393f44ff025ca67716fc53b68003fd65122fd97Jason Evans#include <hardware/hardware.h>
31e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
32e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <gui/GLConsumer.h>
33e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <gui/IGraphicBufferAlloc.h>
3412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans#include <gui/ISurfaceComposer.h>
3512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans#include <gui/SurfaceComposerClient.h>
3612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
3712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans#include <private/gui/ComposerService.h>
387ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <private/gui/SyncFeatures.h>
3912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
407ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <utils/Log.h>
417ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <utils/String8.h>
427ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <utils/Trace.h>
437ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
44609ae595f0358157b19311b0f9f9591db7cee705Jason EvansEGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
45609ae595f0358157b19311b0f9f9591db7cee705Jason Evans#define CROP_EXT_STR "EGL_ANDROID_image_crop"
467ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
477ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansnamespace android {
487ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
497ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans// Macros for including the GLConsumer name in log messages
507ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
517de92767c20cb72c94609b9c78985526fb84a679Jason Evans#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
527ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
5334a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
5434a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
5534a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans
5634a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evansstatic const struct {
5734a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans    size_t width, height;
5834a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans    char const* bits;
5934a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans} kDebugData = { 15, 12,
6034a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans    "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__"
6134a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans    "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________"
6234a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans};
637ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
647ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans// Transform matrices
657ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic float mtxIdentity[16] = {
667ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    1, 0, 0, 0,
677ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, 1, 0, 0,
687ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, 0, 1, 0,
697ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, 0, 0, 1,
70609ae595f0358157b19311b0f9f9591db7cee705Jason Evans};
717ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic float mtxFlipH[16] = {
727ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    -1, 0, 0, 0,
737ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, 1, 0, 0,
747ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, 0, 1, 0,
757ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    1, 0, 0, 1,
767ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans};
77374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evansstatic float mtxFlipV[16] = {
78374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans    1, 0, 0, 0,
797ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, -1, 0, 0,
8014a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    0, 0, 1, 0,
8114a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    0, 1, 0, 1,
8214a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans};
837ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic float mtxRot90[16] = {
84609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    0, 1, 0, 0,
85609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    -1, 0, 0, 0,
867ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    0, 0, 1, 0,
877ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    1, 0, 0, 1,
887ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans};
89609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
90609ae595f0358157b19311b0f9f9591db7cee705Jason Evansstatic void mtxMul(float out[16], const float a[16], const float b[16]);
917ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
927ca0fdfb85b2a9fc7a112e158892c098e004385bJason EvansMutex GLConsumer::sStaticInitLock;
937ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evanssp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
947ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
957ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic bool hasEglAndroidImageCropImpl() {
967ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
977ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
987ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    size_t cropExtLen = strlen(CROP_EXT_STR);
997ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    size_t extsLen = strlen(exts);
1007ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    bool equal = !strcmp(CROP_EXT_STR, exts);
1017ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
1027ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    bool atEnd = (cropExtLen+1) < extsLen &&
1037ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
1047ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
1057ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    return equal || atStart || atEnd || inMiddle;
10612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans}
1077ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
1087ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic bool hasEglAndroidImageCrop() {
1097ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    // Only compute whether the extension is present once the first time this
1107ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    // function is called.
1117ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    static bool hasIt = hasEglAndroidImageCropImpl();
1127ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    return hasIt;
113a7a28c334e5526ba716bf6046eab8d60598183ebJason Evans}
114609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
115609ae595f0358157b19311b0f9f9591db7cee705Jason Evansstatic bool isEglImageCroppable(const Rect& crop) {
1167ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
1177ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans}
1187ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
1197ca0fdfb85b2a9fc7a112e158892c098e004385bJason EvansGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
12014a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans        uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
12112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    ConsumerBase(bq, isControlledByApp),
12214a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mCurrentTransform(0),
12314a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
12414a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mCurrentFence(Fence::NO_FENCE),
12514a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mCurrentTimestamp(0),
12614a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mCurrentFrameNumber(0),
12714a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mDefaultWidth(1),
12814a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mDefaultHeight(1),
129bd87b01999416ec7418ff8bdb504d9b6c009ff68Jason Evans    mFilteringEnabled(true),
13014a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mTexName(tex),
13114a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mUseFenceSync(useFenceSync),
13214a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mTexTarget(texTarget),
13314a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans    mEglDisplay(EGL_NO_DISPLAY),
1347ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    mEglContext(EGL_NO_CONTEXT),
1357ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    mAttached(true)
13741631d00618d7262125e501c91d31b4d70e605faJason Evans{
13841631d00618d7262125e501c91d31b4d70e605faJason Evans    ST_LOGV("GLConsumer");
13941631d00618d7262125e501c91d31b4d70e605faJason Evans
14041631d00618d7262125e501c91d31b4d70e605faJason Evans    memcpy(mCurrentTransformMatrix, mtxIdentity,
14141631d00618d7262125e501c91d31b4d70e605faJason Evans            sizeof(mCurrentTransformMatrix));
14241631d00618d7262125e501c91d31b4d70e605faJason Evans
14359113bcc94b9fc7549611afb99ca99cad1a7f196aravind    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
14459113bcc94b9fc7549611afb99ca99cad1a7f196aravind}
145609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
146e476f8a161d445211fd6e54fe370275196e66bcbJason EvansGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        bool useFenceSync, bool isControlledByApp) :
148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    ConsumerBase(bq, isControlledByApp),
149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    mCurrentTransform(0),
150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
151de6fbdb72c6e1401b36f8f2073404645bac6cd2bJason Evans    mCurrentFence(Fence::NO_FENCE),
152eae269036c9f702d9fa9be497a1a2aa1be13a29eMike Hommey    mCurrentTimestamp(0),
153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    mCurrentFrameNumber(0),
154609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    mDefaultWidth(1),
1554d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans    mDefaultHeight(1),
15612efefb1953062795f5a971c1a72706787c7895cJason Evans    mFilteringEnabled(true),
15712efefb1953062795f5a971c1a72706787c7895cJason Evans    mTexName(-1),
15859113bcc94b9fc7549611afb99ca99cad1a7f196aravind    mUseFenceSync(useFenceSync),
15912efefb1953062795f5a971c1a72706787c7895cJason Evans    mTexTarget(texTarget),
16059113bcc94b9fc7549611afb99ca99cad1a7f196aravind    mEglDisplay(EGL_NO_DISPLAY),
16112efefb1953062795f5a971c1a72706787c7895cJason Evans    mEglContext(EGL_NO_CONTEXT),
162609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
163609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    mAttached(false)
164609ae595f0358157b19311b0f9f9591db7cee705Jason Evans{
16559113bcc94b9fc7549611afb99ca99cad1a7f196aravind    ST_LOGV("GLConsumer");
166609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
16759113bcc94b9fc7549611afb99ca99cad1a7f196aravind    memcpy(mCurrentTransformMatrix, mtxIdentity,
168609ae595f0358157b19311b0f9f9591db7cee705Jason Evans            sizeof(mCurrentTransformMatrix));
1694d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans
17012efefb1953062795f5a971c1a72706787c7895cJason Evans    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
17112efefb1953062795f5a971c1a72706787c7895cJason Evans}
17259113bcc94b9fc7549611afb99ca99cad1a7f196aravind
17312efefb1953062795f5a971c1a72706787c7895cJason Evansstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
17459113bcc94b9fc7549611afb99ca99cad1a7f196aravind    Mutex::Autolock lock(mMutex);
17512efefb1953062795f5a971c1a72706787c7895cJason Evans    return mConsumer->setDefaultMaxBufferCount(bufferCount);
176e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
177e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
17859113bcc94b9fc7549611afb99ca99cad1a7f196aravind
17959113bcc94b9fc7549611afb99ca99cad1a7f196aravindstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
18059113bcc94b9fc7549611afb99ca99cad1a7f196aravind{
18112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    Mutex::Autolock lock(mMutex);
18212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    mDefaultWidth = w;
18359113bcc94b9fc7549611afb99ca99cad1a7f196aravind    mDefaultHeight = h;
18459113bcc94b9fc7549611afb99ca99cad1a7f196aravind    return mConsumer->setDefaultBufferSize(w, h);
18512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans}
18612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
18712141150fdbda57651a53ae2fe0edaea4891d814Jason Evansstatus_t GLConsumer::updateTexImage() {
18812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    ATRACE_CALL();
18912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    ST_LOGV("updateTexImage");
19012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    Mutex::Autolock lock(mMutex);
19112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
19212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (mAbandoned) {
19312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        ST_LOGE("updateTexImage: GLConsumer is abandoned!");
19412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        return NO_INIT;
19512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
19612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
19712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // Make sure the EGL state is the same as in previous calls.
19812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    status_t err = checkAndUpdateEglStateLocked();
19912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (err != NO_ERROR) {
20012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        return err;
20112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
20212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
20312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    BufferQueue::BufferItem item;
20412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
20512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // Acquire the next buffer.
20612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // In asynchronous mode the list is guaranteed to be one buffer
20712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // deep, while in synchronous mode we use the oldest buffer.
20812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    err = acquireBufferLocked(&item, 0);
20912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (err != NO_ERROR) {
21012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
21112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans            // We always bind the texture even if we don't update its contents.
21259113bcc94b9fc7549611afb99ca99cad1a7f196aravind            ST_LOGV("updateTexImage: no buffers were available");
21359113bcc94b9fc7549611afb99ca99cad1a7f196aravind            glBindTexture(mTexTarget, mTexName);
21459113bcc94b9fc7549611afb99ca99cad1a7f196aravind            err = NO_ERROR;
21512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        } else {
21659113bcc94b9fc7549611afb99ca99cad1a7f196aravind            ST_LOGE("updateTexImage: acquire failed: %s (%d)",
21759113bcc94b9fc7549611afb99ca99cad1a7f196aravind                strerror(-err), err);
21812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        }
21959113bcc94b9fc7549611afb99ca99cad1a7f196aravind        return err;
22012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
22112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
22212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // Release the previous buffer.
22312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    err = updateAndReleaseLocked(item);
22412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (err != NO_ERROR) {
22512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        // We always bind the texture.
22612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        glBindTexture(mTexTarget, mTexName);
22712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        return err;
22812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
22912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
23012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // Bind the new buffer to the GL texture, and wait until it's ready.
23159113bcc94b9fc7549611afb99ca99cad1a7f196aravind    return bindTextureImageLocked();
23212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans}
23312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
23412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
23512141150fdbda57651a53ae2fe0edaea4891d814Jason Evansstatus_t GLConsumer::releaseTexImage() {
23612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    ATRACE_CALL();
23712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    ST_LOGV("releaseTexImage");
23812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    Mutex::Autolock lock(mMutex);
23912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
24012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (mAbandoned) {
24112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        ST_LOGE("releaseTexImage: GLConsumer is abandoned!");
242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        return NO_INIT;
24312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    // Make sure the EGL state is the same as in previous calls.
246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    status_t err = NO_ERROR;
24712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
24812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (mAttached) {
24912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        err = checkAndUpdateEglStateLocked(true);
25012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        if (err != NO_ERROR) {
25112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans            return err;
25212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        }
25312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    } else {
25412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        // if we're detached, no need to validate EGL's state -- we won't use it.
25512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
25612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
2577ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    // Update the GLConsumer state.
258609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    int buf = mCurrentTexture;
259609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
2607ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans
2617de92767c20cb72c94609b9c78985526fb84a679Jason Evans        ST_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
2624f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans
2637ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        if (mAttached) {
2647de92767c20cb72c94609b9c78985526fb84a679Jason Evans            // Do whatever sync ops we need to do before releasing the slot.
265bd87b01999416ec7418ff8bdb504d9b6c009ff68Jason Evans            err = syncForReleaseLocked(mEglDisplay);
2667ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            if (err != NO_ERROR) {
267374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans                ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
268374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans                return err;
269374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            }
270374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        } else {
271374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            // if we're detached, we just use the fence that was created in detachFromContext()
272374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            // so... basically, nothing more to do here.
273374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        }
2744f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans
2754f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans        err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
276374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        if (err < NO_ERROR) {
2777ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
278374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans                    strerror(-err), err);
279609ae595f0358157b19311b0f9f9591db7cee705Jason Evans            return err;
280374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        }
281374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans
282374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        if (mReleasedTexImage == NULL) {
283374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
284374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        }
285374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans
286374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
287609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        mCurrentTextureImage = mReleasedTexImage;
288374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        mCurrentCrop.makeInvalid();
289374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        mCurrentTransform = 0;
2907de92767c20cb72c94609b9c78985526fb84a679Jason Evans        mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
291609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        mCurrentTimestamp = 0;
292374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        mCurrentFence = Fence::NO_FENCE;
293374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans
294374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        if (mAttached) {
2957ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            // This binds a dummy buffer (mReleasedTexImage).
296374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            status_t err =  bindTextureImageLocked();
297374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            if (err != NO_ERROR) {
298374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans                return err;
299374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans            }
3007ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        } else {
301741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans            // detached, don't touch the texture (and we may not even have an
3027ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            // EGLDisplay here.
303374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans        }
304741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans    }
305374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans
306374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans    return NO_ERROR;
3077de92767c20cb72c94609b9c78985526fb84a679Jason Evans}
308609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
309609ae595f0358157b19311b0f9f9591db7cee705Jason Evanssp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
3107ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    Mutex::Autolock _l(sStaticInitLock);
3117ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
3127ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        // The first time, create the debug texture in case the application
313609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        // continues to use it.
3147ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        sp<GraphicBuffer> buffer = new GraphicBuffer(
3157ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans                kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
3167ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans                GraphicBuffer::USAGE_SW_WRITE_RARELY);
3177ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        uint32_t* bits;
3187ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
3197ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        size_t w = buffer->getStride();
3207ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        size_t h = buffer->getHeight();
321609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        memset(bits, 0, w*h*4);
322609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        for (size_t y=0 ; y<kDebugData.height ; y++) {
3237ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            for (size_t x=0 ; x<kDebugData.width ; x++) {
324609ae595f0358157b19311b0f9f9591db7cee705Jason Evans                bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF;
3257ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            }
3267ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans            bits += w;
3277de92767c20cb72c94609b9c78985526fb84a679Jason Evans        }
328609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        buffer->unlock();
3297ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans        sReleasedTexImageBuffer = buffer;
3304f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans    }
3317ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    return sReleasedTexImageBuffer;
332741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans}
333741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans
3347ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
3354f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans        nsecs_t presentWhen) {
3364f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
3374f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans    if (err != NO_ERROR) {
3384f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans        return err;
3394f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans    }
34012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
3414f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans    // If item->mGraphicBuffer is not null, this buffer has not been acquired
34212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // before, so any prior EglImage created is using a stale buffer. This
3437ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    // replaces any old EglImage with a new one (using the new buffer).
3447ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans    if (item->mGraphicBuffer != NULL) {
345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        int slot = item->mBuf;
346609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
347609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    }
348609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
349609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    return NO_ERROR;
350609ae595f0358157b19311b0f9f9591db7cee705Jason Evans}
351609ae595f0358157b19311b0f9f9591db7cee705Jason Evans
352609ae595f0358157b19311b0f9f9591db7cee705Jason Evansstatus_t GLConsumer::releaseBufferLocked(int buf,
3534d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans        sp<GraphicBuffer> graphicBuffer,
354609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        EGLDisplay display, EGLSyncKHR eglFence) {
35512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // release the buffer if it hasn't already been discarded by the
356609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    // BufferQueue. This can happen, for example, when the producer of this
357609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    // buffer has reallocated the original buffer slot after this buffer
358609ae595f0358157b19311b0f9f9591db7cee705Jason Evans    // was acquired.
35912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    status_t err = ConsumerBase::releaseBufferLocked(
36012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans            buf, graphicBuffer, display, eglFence);
361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    return err;
363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}
364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
365e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatus_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{
367e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    status_t err = NO_ERROR;
3687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans
369b954bc5d3a65966df0ce7801cd6102542b5e894bJason Evans    int buf = item.mBuf;
3707372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans
3717372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    if (!mAttached) {
372609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
3737372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans                "ES context");
3747372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
3757372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans                mEglDisplay, EGL_NO_SYNC_KHR);
376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        return INVALID_OPERATION;
37712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
37812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
37912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    // Confirm state.
38012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    err = checkAndUpdateEglStateLocked();
38112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    if (err != NO_ERROR) {
38212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
38312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans                mEglDisplay, EGL_NO_SYNC_KHR);
38412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans        return err;
38512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans    }
38612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans
387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    // if nessessary, for the gralloc buffer currently in the slot in
389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    // ConsumerBase.
390a8f8d7540d66ddee7337db80c92890916e1063caJason Evans    // We may have to do this even when item.mGraphicBuffer == NULL (which
391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    // means the buffer was previously acquired).
392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    if (err != NO_ERROR) {
3942dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans        ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
395ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans                mEglDisplay, buf);
396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
397ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans                mEglDisplay, EGL_NO_SYNC_KHR);
398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        return UNKNOWN_ERROR;
3997372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    }
4007372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans
4017372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    // Do whatever sync ops we need to do before releasing the old slot.
4027372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    err = syncForReleaseLocked(mEglDisplay);
4037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    if (err != NO_ERROR) {
4044d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans        // Release the buffer we just acquired.  It's not safe to
405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans        // release the old buffer, so instead we just drop the new frame.
406609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        // As we are still under lock since acquireBuffer, it is safe to
407609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        // release by slot.
408609ae595f0358157b19311b0f9f9591db7cee705Jason Evans        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
409609ae595f0358157b19311b0f9f9591db7cee705Jason Evans                mEglDisplay, EGL_NO_SYNC_KHR);
4107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans        return err;
4117372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    }
412b980cc774a9ccb208a82f4e9ccdcc695d06a960aJason Evans
4137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans    ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
4147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans            mCurrentTexture, mCurrentTextureImage != NULL ?
4157372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans                    mCurrentTextureImage->graphicBufferHandle() : 0,
416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans            buf, mSlots[buf].mGraphicBuffer->handle);
417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans
418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans    // release old buffer
41920f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
42020f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans        status_t status = releaseBufferLocked(
42120f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans                mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
42220f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans                mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
42320f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans        if (status < NO_ERROR) {
424f1c3da8b02489b7728d4275ac011336299eace62Jason Evans            ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
42520f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans                   strerror(-status), status);
42620f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans            err = status;
42720f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans            // keep going, with error raised [?]
42820f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans        }
42920f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    }
43020f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans
43120f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    // Update the GLConsumer state.
43220f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentTexture = buf;
43320f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentTextureImage = mEglSlots[buf].mEglImage;
43420f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentCrop = item.mCrop;
43520f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentTransform = item.mTransform;
43620f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentScalingMode = item.mScalingMode;
43720f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentTimestamp = item.mTimestamp;
43820f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentFence = item.mFence;
43920f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    mCurrentFrameNumber = item.mFrameNumber;
44020f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans
44120f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    computeCurrentTransformMatrixLocked();
44220f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans
44320f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    return err;
44420f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans}
44520f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans
44620f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evansstatus_t GLConsumer::bindTextureImageLocked() {
44720f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans    if (mEglDisplay == EGL_NO_DISPLAY) {
44820f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans        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