SurfaceTexture.cpp revision ed3894c07a67b3e35d07084c4a8b410908bfedc5
168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis/*
268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * Copyright (C) 2010 The Android Open Source Project
368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis *
468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * you may not use this file except in compliance with the License.
668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * You may obtain a copy of the License at
768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis *
868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis *
1068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * Unless required by applicable law or agreed to in writing, software
1168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
1268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * See the License for the specific language governing permissions and
1468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis * limitations under the License.
1568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis */
1668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
1768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#define LOG_TAG "SurfaceTexture"
187dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis//#define LOG_NDEBUG 0
1968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
2068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#define GL_GLEXT_PROTOTYPES
2168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#define EGL_EGLEXT_PROTOTYPES
2268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
2368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <EGL/egl.h>
2468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <EGL/eglext.h>
2568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <GLES2/gl2.h>
2668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <GLES2/gl2ext.h>
2768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
2868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <gui/SurfaceTexture.h>
2968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
3027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian#include <hardware/hardware.h>
3127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
3268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <surfaceflinger/ISurfaceComposer.h>
3368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <surfaceflinger/SurfaceComposerClient.h>
34f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis#include <surfaceflinger/IGraphicBufferAlloc.h>
3568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
3668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis#include <utils/Log.h>
3768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
3868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennisnamespace android {
3968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
40b598fb90727be45e926a11abefc319819a733540Jamie Gennis// Transform matrices
41b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic float mtxIdentity[16] = {
42b598fb90727be45e926a11abefc319819a733540Jamie Gennis    1, 0, 0, 0,
43b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 1, 0, 0,
44b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 1, 0,
45b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 0, 1,
46b598fb90727be45e926a11abefc319819a733540Jamie Gennis};
47b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic float mtxFlipH[16] = {
48b598fb90727be45e926a11abefc319819a733540Jamie Gennis    -1, 0, 0, 0,
49b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 1, 0, 0,
50b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 1, 0,
51b598fb90727be45e926a11abefc319819a733540Jamie Gennis    1, 0, 0, 1,
52b598fb90727be45e926a11abefc319819a733540Jamie Gennis};
53b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic float mtxFlipV[16] = {
54b598fb90727be45e926a11abefc319819a733540Jamie Gennis    1, 0, 0, 0,
55b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, -1, 0, 0,
56b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 1, 0,
57b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 1, 0, 1,
58b598fb90727be45e926a11abefc319819a733540Jamie Gennis};
59b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic float mtxRot90[16] = {
60b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 1, 0, 0,
61b598fb90727be45e926a11abefc319819a733540Jamie Gennis    -1, 0, 0, 0,
62b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 1, 0,
63b598fb90727be45e926a11abefc319819a733540Jamie Gennis    1, 0, 0, 1,
64b598fb90727be45e926a11abefc319819a733540Jamie Gennis};
65b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic float mtxRot180[16] = {
66b598fb90727be45e926a11abefc319819a733540Jamie Gennis    -1, 0, 0, 0,
67b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, -1, 0, 0,
68b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 1, 0,
69b598fb90727be45e926a11abefc319819a733540Jamie Gennis    1, 1, 0, 1,
70b598fb90727be45e926a11abefc319819a733540Jamie Gennis};
71b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic float mtxRot270[16] = {
72b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, -1, 0, 0,
73b598fb90727be45e926a11abefc319819a733540Jamie Gennis    1, 0, 0, 0,
74b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 0, 1, 0,
75b598fb90727be45e926a11abefc319819a733540Jamie Gennis    0, 1, 0, 1,
76b598fb90727be45e926a11abefc319819a733540Jamie Gennis};
77b598fb90727be45e926a11abefc319819a733540Jamie Gennis
78b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]);
79b598fb90727be45e926a11abefc319819a733540Jamie Gennis
8068e4a7ac849b681b1fb769857fc04f64262480c4Jamie GennisSurfaceTexture::SurfaceTexture(GLuint tex) :
81e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    mDefaultWidth(1),
82e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    mDefaultHeight(1),
83e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
84c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mBufferCount(MIN_BUFFER_SLOTS),
85c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mCurrentTexture(INVALID_BUFFER_SLOT),
8627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
87c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mCurrentTransform(0),
88c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mCurrentTimestamp(0),
89c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mLastQueued(INVALID_BUFFER_SLOT),
90c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mLastQueuedTransform(0),
91c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mLastQueuedTimestamp(0),
92c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mNextTransform(0),
93c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mTexName(tex) {
947dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::SurfaceTexture");
95fd804f31a36c31661859b53bbee1bb408462ddcaJamie Gennis    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
96fd804f31a36c31661859b53bbee1bb408462ddcaJamie Gennis        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
97fd804f31a36c31661859b53bbee1bb408462ddcaJamie Gennis        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
98fd804f31a36c31661859b53bbee1bb408462ddcaJamie Gennis        mSlots[i].mOwnedByClient = false;
99fd804f31a36c31661859b53bbee1bb408462ddcaJamie Gennis    }
100f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
101f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
102926340cf56c9a2d21008d050a4e0f1390cf648bfMathias Agopian    mNextCrop.makeInvalid();
10368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
10468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
10568e4a7ac849b681b1fb769857fc04f64262480c4Jamie GennisSurfaceTexture::~SurfaceTexture() {
1067dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::~SurfaceTexture");
10768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    freeAllBuffers();
10868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
10968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
11068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennisstatus_t SurfaceTexture::setBufferCount(int bufferCount) {
1117dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::setBufferCount");
11296dcc978430f0daf6d73fee96a01779ed537a0ceJamie Gennis
11396dcc978430f0daf6d73fee96a01779ed537a0ceJamie Gennis    if (bufferCount < MIN_BUFFER_SLOTS) {
11496dcc978430f0daf6d73fee96a01779ed537a0ceJamie Gennis        return BAD_VALUE;
11596dcc978430f0daf6d73fee96a01779ed537a0ceJamie Gennis    }
11696dcc978430f0daf6d73fee96a01779ed537a0ceJamie Gennis
11768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
11868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    freeAllBuffers();
11968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    mBufferCount = bufferCount;
120d369dc42506ec003f1839bb9e27edada411324b5Jamie Gennis    mCurrentTexture = INVALID_BUFFER_SLOT;
121d369dc42506ec003f1839bb9e27edada411324b5Jamie Gennis    mLastQueued = INVALID_BUFFER_SLOT;
12268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return OK;
12368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
12468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
125e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopianstatus_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
126e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian{
127e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    Mutex::Autolock lock(mMutex);
128e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
129e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        mDefaultWidth = w;
130e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        mDefaultHeight = h;
131e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    }
132e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    return OK;
133e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian}
134e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian
1350297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopiansp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
1367dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::requestBuffer");
13768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
13868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    if (buf < 0 || mBufferCount <= buf) {
13968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
14068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis                mBufferCount, buf);
14168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        return 0;
14268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    }
1430297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    return mSlots[buf].mGraphicBuffer;
1440297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian}
1450297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian
1460297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopianstatus_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
1470297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        uint32_t format, uint32_t usage) {
1480297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    LOGV("SurfaceTexture::dequeueBuffer");
1490297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian
150e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    if ((w && !h) || (!w & h)) {
1510297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
1520297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        return BAD_VALUE;
1530297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    }
1540297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian
1550297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    Mutex::Autolock lock(mMutex);
1560297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    int found = INVALID_BUFFER_SLOT;
1570297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    for (int i = 0; i < mBufferCount; i++) {
1580297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
1590297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian            mSlots[i].mOwnedByClient = true;
1600297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian            found = i;
1610297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian            break;
1620297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        }
163e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    }
1640297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    if (found == INVALID_BUFFER_SLOT) {
1650297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        return -EBUSY;
1660297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    }
1670297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian
1680297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    const int buf = found;
1690297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    *outBuf = found;
170e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian
171e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    const bool useDefaultSize = !w && !h;
172e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    if (useDefaultSize) {
173e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        // use the default size
174e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        w = mDefaultWidth;
175e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        h = mDefaultHeight;
176e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    }
177e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian
178e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    const bool updateFormat = (format != 0);
179e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    if (!updateFormat) {
180e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        // keep the current (or default) format
181e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        format = mPixelFormat;
182e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    }
183e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian
1840297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
1850297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    if ((buffer == NULL) ||
1860297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        (uint32_t(buffer->width)  != w) ||
1870297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        (uint32_t(buffer->height) != h) ||
1880297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        (uint32_t(buffer->format) != format) ||
1890297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        ((uint32_t(buffer->usage) & usage) != usage))
1900297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian    {
1910297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        usage |= GraphicBuffer::USAGE_HW_TEXTURE;
1920297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        sp<GraphicBuffer> graphicBuffer(
1930297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian                mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
1940297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        if (graphicBuffer == 0) {
1950297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian            LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
1960297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian            return NO_MEMORY;
1970297dcae8fddb18ab9e28ba1858a57a8aec3ef32Mathias Agopian        }
198e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        if (updateFormat) {
199e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian            mPixelFormat = format;
200e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        }
20168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        mSlots[buf].mGraphicBuffer = graphicBuffer;
20268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
20368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
20468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
20568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
20668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        }
207e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
208e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian    }
20968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return OK;
21068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
21168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
212c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvalastatus_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
2137dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::queueBuffer");
21468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
21568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    if (buf < 0 || mBufferCount <= buf) {
21668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
21768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis                mBufferCount, buf);
21868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        return -EINVAL;
21968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    } else if (!mSlots[buf].mOwnedByClient) {
22068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("queueBuffer: slot %d is not owned by the client", buf);
22168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        return -EINVAL;
22268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    } else if (mSlots[buf].mGraphicBuffer == 0) {
22368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
22468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis                buf);
22568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        return -EINVAL;
22668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    }
22768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    mSlots[buf].mOwnedByClient = false;
22868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    mLastQueued = buf;
229b598fb90727be45e926a11abefc319819a733540Jamie Gennis    mLastQueuedCrop = mNextCrop;
230b598fb90727be45e926a11abefc319819a733540Jamie Gennis    mLastQueuedTransform = mNextTransform;
231c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    mLastQueuedTimestamp = timestamp;
232376590d668e22a918439877b55faf075427b13f3Jamie Gennis    if (mFrameAvailableListener != 0) {
233376590d668e22a918439877b55faf075427b13f3Jamie Gennis        mFrameAvailableListener->onFrameAvailable();
234376590d668e22a918439877b55faf075427b13f3Jamie Gennis    }
23568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return OK;
23668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
23768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
23868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennisvoid SurfaceTexture::cancelBuffer(int buf) {
2397dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::cancelBuffer");
24068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
24168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    if (buf < 0 || mBufferCount <= buf) {
24268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
24368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis                buf);
24468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        return;
24568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    } else if (!mSlots[buf].mOwnedByClient) {
24668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("cancelBuffer: slot %d is not owned by the client", buf);
24768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        return;
24868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    }
24968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    mSlots[buf].mOwnedByClient = false;
25068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
25168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
252b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatus_t SurfaceTexture::setCrop(const Rect& crop) {
2537dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::setCrop");
25468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
255b598fb90727be45e926a11abefc319819a733540Jamie Gennis    mNextCrop = crop;
25668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return OK;
25768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
25868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
25968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennisstatus_t SurfaceTexture::setTransform(uint32_t transform) {
2607dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::setTransform");
26168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
262b598fb90727be45e926a11abefc319819a733540Jamie Gennis    mNextTransform = transform;
26368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return OK;
26468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
26568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
26668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennisstatus_t SurfaceTexture::updateTexImage() {
2677dc00d5eb27de41f93a7e232b3cd374c84eb77d1Jamie Gennis    LOGV("SurfaceTexture::updateTexImage");
26868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    Mutex::Autolock lock(mMutex);
26968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
27068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
27168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    // so this check will fail until a buffer gets queued.
27268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    if (mCurrentTexture != mLastQueued) {
273b598fb90727be45e926a11abefc319819a733540Jamie Gennis        // Update the GL texture object.
274f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
27568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        if (image == EGL_NO_IMAGE_KHR) {
27668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            EGLDisplay dpy = eglGetCurrentDisplay();
2776fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian            image = createImage(dpy, mSlots[mLastQueued].mGraphicBuffer);
278f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis            mSlots[mLastQueued].mEglImage = image;
279f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis            mSlots[mLastQueued].mEglDisplay = dpy;
2806fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian            if (image == EGL_NO_IMAGE_KHR) {
2816fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian                // NOTE: if dpy was invalid, createImage() is guaranteed to
2826fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian                // fail. so we'd end up here.
2836fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian                return -EINVAL;
2846fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian            }
28568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        }
28679d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis
28779d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        GLint error;
28879d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
28979d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis            LOGE("GL error cleared before updating SurfaceTexture: %#04x", error);
29079d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        }
29127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
29227cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        GLenum target = getTextureTarget(
29327cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian                mSlots[mLastQueued].mGraphicBuffer->format);
29427cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        if (target != mCurrentTextureTarget) {
29527cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian            glDeleteTextures(1, &mTexName);
29627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        }
29727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        glBindTexture(target, mTexName);
29827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
29927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
30079d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        bool failed = false;
30179d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        while ((error = glGetError()) != GL_NO_ERROR) {
30268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            LOGE("error binding external texture image %p (slot %d): %#04x",
303f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis                    image, mLastQueued, error);
30479d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis            failed = true;
30579d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        }
30679d01fe8232c67a18aeb8784c2b8783358ec4e44Jamie Gennis        if (failed) {
30768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            return -EINVAL;
30868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        }
309f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis
310f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis        // Update the SurfaceTexture state.
311f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis        mCurrentTexture = mLastQueued;
31227cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        mCurrentTextureTarget = target;
313f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
314f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis        mCurrentCrop = mLastQueuedCrop;
315f7acf162f8d682c6ebc9af41ca76795b79509193Jamie Gennis        mCurrentTransform = mLastQueuedTransform;
316c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala        mCurrentTimestamp = mLastQueuedTimestamp;
31727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    } else {
31827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        // We always bind the texture even if we don't update its contents.
31927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        glBindTexture(mCurrentTextureTarget, mTexName);
32068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    }
32168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return OK;
32268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
32368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
32427cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopianbool SurfaceTexture::isExternalFormat(uint32_t format)
32527cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian{
32627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    switch (format) {
32727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    // supported YUV formats
32827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    case HAL_PIXEL_FORMAT_YV12:
32927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    // Legacy/deprecated YUV formats
33027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
33127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
33227cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    case HAL_PIXEL_FORMAT_YCbCr_422_I:
33327cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        return true;
33427cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    }
33527cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
33627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    // Any OEM format needs to be considered
33727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    if (format>=0x100 && format<=0x1FF)
33827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        return true;
33927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
34027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    return false;
34127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian}
34227cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
34327cd07ca8006fd80d85379ada416874bfa78aa88Mathias AgopianGLenum SurfaceTexture::getTextureTarget(uint32_t format)
34427cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian{
34527cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    GLenum target = GL_TEXTURE_2D;
34627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian#if defined(GL_OES_EGL_image_external)
34727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    if (isExternalFormat(format)) {
34827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian        target = GL_TEXTURE_EXTERNAL_OES;
34927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    }
35027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian#endif
35127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    return target;
35227cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian}
35327cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
35427cd07ca8006fd80d85379ada416874bfa78aa88Mathias AgopianGLenum SurfaceTexture::getCurrentTextureTarget() const {
35527cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    Mutex::Autolock lock(mMutex);
35627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    return mCurrentTextureTarget;
35727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian}
35827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
359b598fb90727be45e926a11abefc319819a733540Jamie Gennisvoid SurfaceTexture::getTransformMatrix(float mtx[16]) {
360c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    LOGV("SurfaceTexture::getTransformMatrix");
361b598fb90727be45e926a11abefc319819a733540Jamie Gennis    Mutex::Autolock lock(mMutex);
362b598fb90727be45e926a11abefc319819a733540Jamie Gennis
3630fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    float xform[16];
3640fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    for (int i = 0; i < 16; i++) {
3650fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        xform[i] = mtxIdentity[i];
3660fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    }
3670fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
3680fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        float result[16];
3690fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        mtxMul(result, xform, mtxFlipH);
3700fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        for (int i = 0; i < 16; i++) {
3710fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis            xform[i] = result[i];
3720fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        }
3730fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    }
3740fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
3750fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        float result[16];
3760fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        mtxMul(result, xform, mtxFlipV);
3770fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        for (int i = 0; i < 16; i++) {
3780fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis            xform[i] = result[i];
3790fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        }
3800fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    }
3810fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
3820fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        float result[16];
3830fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        mtxMul(result, xform, mtxRot90);
3840fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        for (int i = 0; i < 16; i++) {
3850fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis            xform[i] = result[i];
3860fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        }
387b598fb90727be45e926a11abefc319819a733540Jamie Gennis    }
388b598fb90727be45e926a11abefc319819a733540Jamie Gennis
389b598fb90727be45e926a11abefc319819a733540Jamie Gennis    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
3900fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    float tx, ty, sx, sy;
3910fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    if (!mCurrentCrop.isEmpty()) {
392f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // In order to prevent bilinear sampling at the of the crop rectangle we
393f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // may need to shrink it by 2 texels in each direction.  Normally this
394f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // would just need to take 1/2 a texel off each end, but because the
395f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // chroma channels will likely be subsampled we need to chop off a whole
396f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // texel.  This will cause artifacts if someone does nearest sampling
397f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
398f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // accomodate the bilinear and nearest sampling uses.
399f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        //
400f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // If nearest sampling turns out to be a desirable usage of these
401f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // textures then we could add the ability to switch a SurfaceTexture to
402f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // nearest-mode.  Preferably, however, the image producers (video
403f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // decoder, camera, etc.) would simply not use a crop rectangle (or at
404f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // least not tell the framework about it) so that the GPU can do the
405f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        // correct edge behavior.
406f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        int xshrink = 0, yshrink = 0;
407f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        if (mCurrentCrop.left > 0) {
408f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
409f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            xshrink++;
410f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        } else {
411f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            tx = 0.0f;
412f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        }
413e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        if (mCurrentCrop.right < int32_t(buf->getWidth())) {
414f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            xshrink++;
415f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        }
416e5a1bffd9106b1d82259de1a202e1f2f28742392Mathias Agopian        if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
417f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
418f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis                    float(buf->getHeight());
419f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            yshrink++;
420f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        } else {
421f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            ty = 0.0f;
422f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        }
423f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        if (mCurrentCrop.top > 0) {
424f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis            yshrink++;
425f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        }
426f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
427f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
4280fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    } else {
4290fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        tx = 0.0f;
4300fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        ty = 0.0f;
4310fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        sx = 1.0f;
4320fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        sy = 1.0f;
4330fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    }
434b598fb90727be45e926a11abefc319819a733540Jamie Gennis    float crop[16] = {
4350fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        sx, 0, 0, 0,
4360fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis        0, sy, 0, 0,
437b598fb90727be45e926a11abefc319819a733540Jamie Gennis        0, 0, 1, 0,
438f3cedb602197a6255e3a7b005cc368577d75bf3aJamie Gennis        tx, ty, 0, 1,
439b598fb90727be45e926a11abefc319819a733540Jamie Gennis    };
440b598fb90727be45e926a11abefc319819a733540Jamie Gennis
4410fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    float mtxBeforeFlipV[16];
4420fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    mtxMul(mtxBeforeFlipV, crop, xform);
4430fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis
4440fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    // SurfaceFlinger expects the top of its window textures to be at a Y
4450fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
4460fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    // want to expose this to applications, however, so we must add an
4470fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    // additional vertical flip to the transform after all the other transforms.
4480fb736c0937d9d65001e0176d90e1011226594bfJamie Gennis    mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
449b598fb90727be45e926a11abefc319819a733540Jamie Gennis}
450b598fb90727be45e926a11abefc319819a733540Jamie Gennis
451c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvalansecs_t SurfaceTexture::getTimestamp() {
452c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    LOGV("SurfaceTexture::getTimestamp");
453c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    Mutex::Autolock lock(mMutex);
454c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala    return mCurrentTimestamp;
455c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala}
456c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala
457376590d668e22a918439877b55faf075427b13f3Jamie Gennisvoid SurfaceTexture::setFrameAvailableListener(
458376590d668e22a918439877b55faf075427b13f3Jamie Gennis        const sp<FrameAvailableListener>& l) {
459376590d668e22a918439877b55faf075427b13f3Jamie Gennis    LOGV("SurfaceTexture::setFrameAvailableListener");
460376590d668e22a918439877b55faf075427b13f3Jamie Gennis    Mutex::Autolock lock(mMutex);
461376590d668e22a918439877b55faf075427b13f3Jamie Gennis    mFrameAvailableListener = l;
462376590d668e22a918439877b55faf075427b13f3Jamie Gennis}
463376590d668e22a918439877b55faf075427b13f3Jamie Gennis
46483bac216a7ba8493a7916e40b2555e73c3a5cc1aJamie Gennissp<IBinder> SurfaceTexture::getAllocator() {
46583bac216a7ba8493a7916e40b2555e73c3a5cc1aJamie Gennis    LOGV("SurfaceTexture::getAllocator");
46683bac216a7ba8493a7916e40b2555e73c3a5cc1aJamie Gennis    return mGraphicBufferAlloc->asBinder();
46783bac216a7ba8493a7916e40b2555e73c3a5cc1aJamie Gennis}
46883bac216a7ba8493a7916e40b2555e73c3a5cc1aJamie Gennis
46968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennisvoid SurfaceTexture::freeAllBuffers() {
47068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
47168e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        mSlots[i].mGraphicBuffer = 0;
47268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        mSlots[i].mOwnedByClient = false;
47368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
47468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
47568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
47668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
47768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        }
47868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    }
47968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
48068e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
48168e4a7ac849b681b1fb769857fc04f64262480c4Jamie GennisEGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
48268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        const sp<GraphicBuffer>& graphicBuffer) {
48368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
48468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    EGLint attrs[] = {
48568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
48668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        EGL_NONE,
48768e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    };
48868e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
48968e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
4906fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian    if (image == EGL_NO_IMAGE_KHR) {
4916fad64c747040e6abcc6a57b99e5ba9293ee4d99Mathias Agopian        EGLint error = eglGetError();
49268e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis        LOGE("error creating EGLImage: %#x", error);
49368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    }
49468e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis    return image;
49568e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}
49668e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis
49727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopiansp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
49827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    Mutex::Autolock lock(mMutex);
49927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    return mCurrentTextureBuf;
50027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian}
50127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
50227cd07ca8006fd80d85379ada416874bfa78aa88Mathias AgopianRect SurfaceTexture::getCurrentCrop() const {
50327cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    Mutex::Autolock lock(mMutex);
50427cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    return mCurrentCrop;
50527cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian}
50627cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
50727cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopianuint32_t SurfaceTexture::getCurrentTransform() const {
50827cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    Mutex::Autolock lock(mMutex);
50927cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian    return mCurrentTransform;
51027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian}
51127cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
512ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopianint SurfaceTexture::query(int what, int* outValue)
513ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian{
514ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    Mutex::Autolock lock(mMutex);
515ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    int value;
516ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    switch (what) {
517ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    case NATIVE_WINDOW_WIDTH:
518ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        value = mDefaultWidth;
519ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
520ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian            value = mCurrentTextureBuf->width;
521ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        break;
522ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    case NATIVE_WINDOW_HEIGHT:
523ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        value = mDefaultHeight;
524ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
525ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian            value = mCurrentTextureBuf->height;
526ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        break;
527ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    case NATIVE_WINDOW_FORMAT:
528ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        value = mPixelFormat;
529ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        break;
530ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
531ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        value = mSynchronousMode ?
532ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
533ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        break;
534ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    default:
535ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian        return BAD_VALUE;
536ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    }
537ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    outValue[0] = value;
538ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian    return NO_ERROR;
539ed3894c07a67b3e35d07084c4a8b410908bfedc5Mathias Agopian}
54027cd07ca8006fd80d85379ada416874bfa78aa88Mathias Agopian
541b598fb90727be45e926a11abefc319819a733540Jamie Gennisstatic void mtxMul(float out[16], const float a[16], const float b[16]) {
542b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
543b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
544b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
545b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
546b598fb90727be45e926a11abefc319819a733540Jamie Gennis
547b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
548b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
549b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
550b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
551b598fb90727be45e926a11abefc319819a733540Jamie Gennis
552b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
553b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
554b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
555b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
556b598fb90727be45e926a11abefc319819a733540Jamie Gennis
557b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
558b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
559b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
560b598fb90727be45e926a11abefc319819a733540Jamie Gennis    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
561b598fb90727be45e926a11abefc319819a733540Jamie Gennis}
562b598fb90727be45e926a11abefc319819a733540Jamie Gennis
56368e4a7ac849b681b1fb769857fc04f64262480c4Jamie Gennis}; // namespace android
564