GLConsumer.cpp revision 3cd5a117083e6a53b9946e8c316377658ab79b3d
18ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/*
28ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Copyright (C) 2010 The Android Open Source Project
38ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
48ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
58ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * you may not use this file except in compliance with the License.
68ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * You may obtain a copy of the License at
78ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
88ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
98ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis *
108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * Unless required by applicable law or agreed to in writing, software
118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * See the License for the specific language governing permissions and
148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * limitations under the License.
158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis */
168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define LOG_TAG "SurfaceTexture"
18e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis//#define LOG_NDEBUG 0
198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define GL_GLEXT_PROTOTYPES
218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define EGL_EGLEXT_PROTOTYPES
228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/egl.h>
248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <EGL/eglext.h>
258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2.h>
268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <GLES2/gl2ext.h>
278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
288ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <gui/SurfaceTexture.h>
298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian#include <hardware/hardware.h>
317a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
328ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <surfaceflinger/ISurfaceComposer.h>
338ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <surfaceflinger/SurfaceComposerClient.h>
349a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis#include <surfaceflinger/IGraphicBufferAlloc.h>
358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <utils/Log.h>
378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisnamespace android {
398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
40f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis// Transform matrices
41f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxIdentity[16] = {
42f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
43f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
44f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
45f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 0, 1,
46f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
47f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipH[16] = {
48f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
49f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
50f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
51f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
52f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
53f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxFlipV[16] = {
54f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
55f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
56f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
57f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
58f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
59f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot90[16] = {
60f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 0,
61f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
62f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
63f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 1,
64f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
65f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot180[16] = {
66f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    -1, 0, 0, 0,
67f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
68f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
69f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 1, 0, 1,
70f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
71f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic float mtxRot270[16] = {
72f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, -1, 0, 0,
73f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    1, 0, 0, 0,
74f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 0, 1, 0,
75f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    0, 1, 0, 1,
76f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis};
77f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
78f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
79f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
808ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisSurfaceTexture::SurfaceTexture(GLuint tex) :
81a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mDefaultWidth(1),
82a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mDefaultHeight(1),
83a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
84a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    mUseDefaultSize(true),
851d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mBufferCount(MIN_BUFFER_SLOTS),
861d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTexture(INVALID_BUFFER_SLOT),
877a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
881d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTransform(0),
891d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mCurrentTimestamp(0),
901d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mLastQueued(INVALID_BUFFER_SLOT),
911d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mLastQueuedTransform(0),
921d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mLastQueuedTimestamp(0),
931d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mNextTransform(0),
941d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mTexName(tex) {
95e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::SurfaceTexture");
963461e0fadff06f77874676a90d4ea12c0405a925Jamie Gennis    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
973461e0fadff06f77874676a90d4ea12c0405a925Jamie Gennis        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
983461e0fadff06f77874676a90d4ea12c0405a925Jamie Gennis        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
993461e0fadff06f77874676a90d4ea12c0405a925Jamie Gennis        mSlots[i].mOwnedByClient = false;
1003461e0fadff06f77874676a90d4ea12c0405a925Jamie Gennis    }
1019a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
1029a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
1038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1048ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisSurfaceTexture::~SurfaceTexture() {
106e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::~SurfaceTexture");
1078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    freeAllBuffers();
1088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::setBufferCount(int bufferCount) {
111e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::setBufferCount");
1129d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis
1139d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis    if (bufferCount < MIN_BUFFER_SLOTS) {
1149d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis        return BAD_VALUE;
1159d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis    }
1169d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6Jamie Gennis
1178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
1188ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    freeAllBuffers();
1198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    mBufferCount = bufferCount;
12067eedd74ab78c2bfed9fcdc74947b97289254ca4Jamie Gennis    mCurrentTexture = INVALID_BUFFER_SLOT;
12167eedd74ab78c2bfed9fcdc74947b97289254ca4Jamie Gennis    mLastQueued = INVALID_BUFFER_SLOT;
1228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
1238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
125a5c75c01620179ce00812354778a29a80d76e71fMathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
126a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian{
127a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    Mutex::Autolock lock(mMutex);
128a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
129a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        mDefaultWidth = w;
130a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        mDefaultHeight = h;
131a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
132a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    return OK;
133a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian}
134a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennissp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
1368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
137e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::requestBuffer");
1388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
1398ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (buf < 0 || mBufferCount <= buf) {
1408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
1418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                mBufferCount, buf);
1428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return 0;
1438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
144a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if ((w && !h) || (!w & h)) {
145a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        LOGE("requestBuffer: invalid size: w=%u, h=%u: %d", w, h, buf);
146a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        return 0;
147a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
148a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
149a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    const bool useDefaultSize = !w && !h;
150a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if (useDefaultSize) {
151a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        // use the default size
152a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        w = mDefaultWidth;
153a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        h = mDefaultHeight;
154a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
155a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
156a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    const bool updateFormat = (format != 0);
157a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if (!updateFormat) {
158a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        // keep the current (or default) format
159a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        format = mPixelFormat;
160a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
161a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1628ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
1639a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis    sp<GraphicBuffer> graphicBuffer(
1649a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis            mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
1658ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (graphicBuffer == 0) {
1668ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
1678ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    } else {
168a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        mUseDefaultSize = useDefaultSize;
169a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (updateFormat) {
170a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian            mPixelFormat = format;
171a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        }
1728ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        mSlots[buf].mGraphicBuffer = graphicBuffer;
1738ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
1748ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
1758ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
1768ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
1778ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
1788ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
1798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return graphicBuffer;
1808ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
1818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
1828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::dequeueBuffer(int *buf) {
183e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::dequeueBuffer");
1848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
1858ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    int found = INVALID_BUFFER_SLOT;
1868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    for (int i = 0; i < mBufferCount; i++) {
187235c424c9a2e3cc5c24aae8bd9cc6f9db0808b42Jamie Gennis        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
1888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[i].mOwnedByClient = true;
1898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            found = i;
1908ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            break;
1918ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
1928ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
1938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (found == INVALID_BUFFER_SLOT) {
1948ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return -EBUSY;
1958ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
196a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
1978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    *buf = found;
198a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian
199a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
200a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if (buffer == NULL) {
201a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
202a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
2037a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
204a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    if ((mUseDefaultSize) &&
205a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        ((uint32_t(buffer->width) != mDefaultWidth) ||
206a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian         (uint32_t(buffer->height) != mDefaultHeight))) {
207a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
208a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian    }
2098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2121d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalastatus_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
213e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::queueBuffer");
2148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
2158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (buf < 0 || mBufferCount <= buf) {
2168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
2178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                mBufferCount, buf);
2188ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return -EINVAL;
2198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    } else if (!mSlots[buf].mOwnedByClient) {
2208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("queueBuffer: slot %d is not owned by the client", buf);
2218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return -EINVAL;
2228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    } else if (mSlots[buf].mGraphicBuffer == 0) {
2238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
2248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                buf);
2258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return -EINVAL;
2268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
2278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    mSlots[buf].mOwnedByClient = false;
2288ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    mLastQueued = buf;
229f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    mLastQueuedCrop = mNextCrop;
230f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    mLastQueuedTransform = mNextTransform;
2311d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    mLastQueuedTimestamp = timestamp;
232c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    if (mFrameAvailableListener != 0) {
233c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis        mFrameAvailableListener->onFrameAvailable();
234c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    }
2358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisvoid SurfaceTexture::cancelBuffer(int buf) {
239e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::cancelBuffer");
2408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
2418ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (buf < 0 || mBufferCount <= buf) {
2428ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
2438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis                buf);
2448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return;
2458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    } else if (!mSlots[buf].mOwnedByClient) {
2468ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("cancelBuffer: slot %d is not owned by the client", buf);
2478ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        return;
2488ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
2498ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    mSlots[buf].mOwnedByClient = false;
2508ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2518ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
252f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatus_t SurfaceTexture::setCrop(const Rect& crop) {
253e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::setCrop");
2548ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
255f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    mNextCrop = crop;
2568ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2578ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2588ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2598ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::setTransform(uint32_t transform) {
260e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::setTransform");
2618ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
262f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    mNextTransform = transform;
2638ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
2648ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
2658ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2668ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatus_t SurfaceTexture::updateTexImage() {
267e70d8b43938e17beebcc0c97a9373a1906f6f2bfJamie Gennis    LOGV("SurfaceTexture::updateTexImage");
2688ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    Mutex::Autolock lock(mMutex);
2698ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
2708ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
2718ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    // so this check will fail until a buffer gets queued.
2728ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    if (mCurrentTexture != mLastQueued) {
273f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        // Update the GL texture object.
2749a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
2758ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
2768ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGLDisplay dpy = eglGetCurrentDisplay();
2773cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            image = createImage(dpy, mSlots[mLastQueued].mGraphicBuffer);
2789a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis            mSlots[mLastQueued].mEglImage = image;
2799a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis            mSlots[mLastQueued].mEglDisplay = dpy;
2803cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            if (image == EGL_NO_IMAGE_KHR) {
2813cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // NOTE: if dpy was invalid, createImage() is guaranteed to
2823cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                // fail. so we'd end up here.
2833cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian                return -EINVAL;
2843cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian            }
2858ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
2860eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis
2870eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        GLint error;
2880eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
2890eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis            LOGE("GL error cleared before updating SurfaceTexture: %#04x", error);
2900eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
2917a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
2927a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        GLenum target = getTextureTarget(
2937a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian                mSlots[mLastQueued].mGraphicBuffer->format);
2947a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        if (target != mCurrentTextureTarget) {
2957a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian            glDeleteTextures(1, &mTexName);
2967a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        }
2977a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        glBindTexture(target, mTexName);
2987a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
2997a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3000eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        bool failed = false;
3010eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
3028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            LOGE("error binding external texture image %p (slot %d): %#04x",
3039a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis                    image, mLastQueued, error);
3040eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis            failed = true;
3050eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        }
3060eb8851e8cc35f443646000220e42dba3adfab8bJamie Gennis        if (failed) {
3078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            return -EINVAL;
3088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
3099a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis
3109a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        // Update the SurfaceTexture state.
3119a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        mCurrentTexture = mLastQueued;
3127a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        mCurrentTextureTarget = target;
3139a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
3149a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        mCurrentCrop = mLastQueuedCrop;
3159a78c90cd46b2a3bd637b056873149d3b94384b4Jamie Gennis        mCurrentTransform = mLastQueuedTransform;
3161d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala        mCurrentTimestamp = mLastQueuedTimestamp;
3177a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    } else {
3187a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        // We always bind the texture even if we don't update its contents.
3197a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        glBindTexture(mCurrentTextureTarget, mTexName);
3208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
3218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return OK;
3228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
3238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
3247a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
3257a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
3267a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    switch (format) {
3277a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // supported YUV formats
3287a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
3297a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Legacy/deprecated YUV formats
3307a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
3317a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
3327a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
3337a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
3347a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
3357a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3367a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    // Any OEM format needs to be considered
3377a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (format>=0x100 && format<=0x1FF)
3387a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        return true;
3397a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3407a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return false;
3417a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
3427a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3437a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getTextureTarget(uint32_t format)
3447a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian{
3457a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    GLenum target = GL_TEXTURE_2D;
3467a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian#if defined(GL_OES_EGL_image_external)
3477a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    if (isExternalFormat(format)) {
3487a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian        target = GL_TEXTURE_EXTERNAL_OES;
3497a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    }
3507a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian#endif
3517a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return target;
3527a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
3537a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
3547a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
3557a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
3567a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureTarget;
3577a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
3587a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
359f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
3601d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    LOGV("SurfaceTexture::getTransformMatrix");
361f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    Mutex::Autolock lock(mMutex);
362f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
363a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float xform[16];
364a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    for (int i = 0; i < 16; i++) {
365a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        xform[i] = mtxIdentity[i];
366a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
367a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
368a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
369a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipH);
370a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
371a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
372a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
373a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
374a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
375a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
376a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxFlipV);
377a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
378a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
379a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
380a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
381a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
382a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        float result[16];
383a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        mtxMul(result, xform, mtxRot90);
384a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        for (int i = 0; i < 16; i++) {
385a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis            xform[i] = result[i];
386a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        }
387f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    }
388f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
389f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
390a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float tx, ty, sx, sy;
391a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    if (!mCurrentCrop.isEmpty()) {
392d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // In order to prevent bilinear sampling at the of the crop rectangle we
393d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // may need to shrink it by 2 texels in each direction.  Normally this
394d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // would just need to take 1/2 a texel off each end, but because the
395d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // chroma channels will likely be subsampled we need to chop off a whole
396d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // texel.  This will cause artifacts if someone does nearest sampling
397d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
398d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // accomodate the bilinear and nearest sampling uses.
399d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        //
400d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // If nearest sampling turns out to be a desirable usage of these
401d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // textures then we could add the ability to switch a SurfaceTexture to
402d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // nearest-mode.  Preferably, however, the image producers (video
403d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // decoder, camera, etc.) would simply not use a crop rectangle (or at
404d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // least not tell the framework about it) so that the GPU can do the
405d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // correct edge behavior.
406d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        int xshrink = 0, yshrink = 0;
407d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.left > 0) {
408d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
409d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
410d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
411d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            tx = 0.0f;
412d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
413a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
414d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            xshrink++;
415d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
416a5c75c01620179ce00812354778a29a80d76e71fMathias Agopian        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
417d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
418d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    float(buf->getHeight());
419d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
420d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
421d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ty = 0.0f;
422d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
423d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mCurrentCrop.top > 0) {
424d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yshrink++;
425d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
426d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
427d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
428a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    } else {
429a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        tx = 0.0f;
430a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        ty = 0.0f;
431a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx = 1.0f;
432a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sy = 1.0f;
433a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    }
434f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    float crop[16] = {
435a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        sx, 0, 0, 0,
436a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis        0, sy, 0, 0,
437f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis        0, 0, 1, 0,
438d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        tx, ty, 0, 1,
439f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    };
440f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
441a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    float mtxBeforeFlipV[16];
442a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
443a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis
444a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
445a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
446a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // want to expose this to applications, however, so we must add an
447a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    // additional vertical flip to the transform after all the other transforms.
448a214c64d7fb3baf9138cc5314f2111ecf5056c6cJamie Gennis    mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
449f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
450f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
4511d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
4521d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    LOGV("SurfaceTexture::getTimestamp");
4531d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    Mutex::Autolock lock(mMutex);
4541d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala    return mCurrentTimestamp;
4551d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala}
4561d01a12e7150be569557b64da9b8663c62c13594Eino-Ville Talvala
457c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennisvoid SurfaceTexture::setFrameAvailableListener(
458c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis        const sp<FrameAvailableListener>& l) {
459c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    LOGV("SurfaceTexture::setFrameAvailableListener");
460c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    Mutex::Autolock lock(mMutex);
461c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis    mFrameAvailableListener = l;
462c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis}
463c4d4aeab52435c177ded6abdd578fec8191f0f5dJamie Gennis
4641b20cde313b5ef8acdace742328df867956d24cbJamie Gennissp<IBinder> SurfaceTexture::getAllocator() {
4651b20cde313b5ef8acdace742328df867956d24cbJamie Gennis    LOGV("SurfaceTexture::getAllocator");
4661b20cde313b5ef8acdace742328df867956d24cbJamie Gennis    return mGraphicBufferAlloc->asBinder();
4671b20cde313b5ef8acdace742328df867956d24cbJamie Gennis}
4681b20cde313b5ef8acdace742328df867956d24cbJamie Gennis
4698ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisvoid SurfaceTexture::freeAllBuffers() {
4708ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
4718ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        mSlots[i].mGraphicBuffer = 0;
4728ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        mSlots[i].mOwnedByClient = false;
4738ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
4748ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
4758ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
4768ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
4778ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        }
4788ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
4798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
4808ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
4828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
4838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
4848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLint attrs[] = {
4858ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
4868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        EGL_NONE,
4878ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    };
4888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
4898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
4903cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
4913cd5a117083e6a53b9946e8c316377658ab79b3dMathias Agopian        EGLint error = eglGetError();
4928ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis        LOGE("error creating EGLImage: %#x", error);
4938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    }
4948ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis    return image;
4958ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}
4968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis
4977a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
4987a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
4997a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTextureBuf;
5007a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5017a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5027a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
5037a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
5047a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentCrop;
5057a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5067a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5077a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
5087a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    Mutex::Autolock lock(mMutex);
5097a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian    return mCurrentTransform;
5107a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian}
5117a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
5127a042bf324fe3f3d5d4085fda21fe50dc0c362b4Mathias Agopian
513f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
514f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
515f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
516f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
517f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
518f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
519f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
520f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
521f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
522f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
523f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
524f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
525f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
526f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
527f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
528f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
529f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
530f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
531f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
532f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
533f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis}
534f238e28500ca756fbd9e323f728ce7c8dda59475Jamie Gennis
5358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis}; // namespace android
536