SurfaceTexture.cpp revision 376590d668e22a918439877b55faf075427b13f3
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "SurfaceTexture"
18//#define LOG_NDEBUG 0
19
20#define GL_GLEXT_PROTOTYPES
21#define EGL_EGLEXT_PROTOTYPES
22
23#include <EGL/egl.h>
24#include <EGL/eglext.h>
25#include <GLES2/gl2.h>
26#include <GLES2/gl2ext.h>
27
28#include <gui/SurfaceTexture.h>
29
30#include <surfaceflinger/ISurfaceComposer.h>
31#include <surfaceflinger/SurfaceComposerClient.h>
32#include <surfaceflinger/IGraphicBufferAlloc.h>
33
34#include <utils/Log.h>
35
36namespace android {
37
38// Transform matrices
39static float mtxIdentity[16] = {
40    1, 0, 0, 0,
41    0, 1, 0, 0,
42    0, 0, 1, 0,
43    0, 0, 0, 1,
44};
45static float mtxFlipH[16] = {
46    -1, 0, 0, 0,
47    0, 1, 0, 0,
48    0, 0, 1, 0,
49    1, 0, 0, 1,
50};
51static float mtxFlipV[16] = {
52    1, 0, 0, 0,
53    0, -1, 0, 0,
54    0, 0, 1, 0,
55    0, 1, 0, 1,
56};
57static float mtxRot90[16] = {
58    0, 1, 0, 0,
59    -1, 0, 0, 0,
60    0, 0, 1, 0,
61    1, 0, 0, 1,
62};
63static float mtxRot180[16] = {
64    -1, 0, 0, 0,
65    0, -1, 0, 0,
66    0, 0, 1, 0,
67    1, 1, 0, 1,
68};
69static float mtxRot270[16] = {
70    0, -1, 0, 0,
71    1, 0, 0, 0,
72    0, 0, 1, 0,
73    0, 1, 0, 1,
74};
75
76static void mtxMul(float out[16], const float a[16], const float b[16]);
77
78SurfaceTexture::SurfaceTexture(GLuint tex) :
79    mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
80    mLastQueued(INVALID_BUFFER_SLOT), mTexName(tex) {
81    LOGV("SurfaceTexture::SurfaceTexture");
82    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
83        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
84        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
85        mSlots[i].mOwnedByClient = false;
86    }
87    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
88    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
89}
90
91SurfaceTexture::~SurfaceTexture() {
92    LOGV("SurfaceTexture::~SurfaceTexture");
93    freeAllBuffers();
94}
95
96status_t SurfaceTexture::setBufferCount(int bufferCount) {
97    LOGV("SurfaceTexture::setBufferCount");
98    Mutex::Autolock lock(mMutex);
99    freeAllBuffers();
100    mBufferCount = bufferCount;
101    mCurrentTexture = INVALID_BUFFER_SLOT;
102    mLastQueued = INVALID_BUFFER_SLOT;
103    return OK;
104}
105
106sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
107        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
108    LOGV("SurfaceTexture::requestBuffer");
109    Mutex::Autolock lock(mMutex);
110    if (buf < 0 || mBufferCount <= buf) {
111        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
112                mBufferCount, buf);
113        return 0;
114    }
115    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
116    sp<GraphicBuffer> graphicBuffer(
117            mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
118    if (graphicBuffer == 0) {
119        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
120    } else {
121        mSlots[buf].mGraphicBuffer = graphicBuffer;
122        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
123            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
124            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
125            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
126        }
127        mAllocdBuffers.add(graphicBuffer);
128    }
129    return graphicBuffer;
130}
131
132status_t SurfaceTexture::dequeueBuffer(int *buf) {
133    LOGV("SurfaceTexture::dequeueBuffer");
134    Mutex::Autolock lock(mMutex);
135    int found = INVALID_BUFFER_SLOT;
136    for (int i = 0; i < mBufferCount; i++) {
137        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
138            mSlots[i].mOwnedByClient = true;
139            found = i;
140            break;
141        }
142    }
143    if (found == INVALID_BUFFER_SLOT) {
144        return -EBUSY;
145    }
146    *buf = found;
147    return OK;
148}
149
150status_t SurfaceTexture::queueBuffer(int buf) {
151    LOGV("SurfaceTexture::queueBuffer");
152    Mutex::Autolock lock(mMutex);
153    if (buf < 0 || mBufferCount <= buf) {
154        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
155                mBufferCount, buf);
156        return -EINVAL;
157    } else if (!mSlots[buf].mOwnedByClient) {
158        LOGE("queueBuffer: slot %d is not owned by the client", buf);
159        return -EINVAL;
160    } else if (mSlots[buf].mGraphicBuffer == 0) {
161        LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
162                buf);
163        return -EINVAL;
164    }
165    mSlots[buf].mOwnedByClient = false;
166    mLastQueued = buf;
167    mLastQueuedCrop = mNextCrop;
168    mLastQueuedTransform = mNextTransform;
169    if (mFrameAvailableListener != 0) {
170        mFrameAvailableListener->onFrameAvailable();
171    }
172    return OK;
173}
174
175void SurfaceTexture::cancelBuffer(int buf) {
176    LOGV("SurfaceTexture::cancelBuffer");
177    Mutex::Autolock lock(mMutex);
178    if (buf < 0 || mBufferCount <= buf) {
179        LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
180                buf);
181        return;
182    } else if (!mSlots[buf].mOwnedByClient) {
183        LOGE("cancelBuffer: slot %d is not owned by the client", buf);
184        return;
185    }
186    mSlots[buf].mOwnedByClient = false;
187}
188
189status_t SurfaceTexture::setCrop(const Rect& crop) {
190    LOGV("SurfaceTexture::setCrop");
191    Mutex::Autolock lock(mMutex);
192    mNextCrop = crop;
193    return OK;
194}
195
196status_t SurfaceTexture::setTransform(uint32_t transform) {
197    LOGV("SurfaceTexture::setTransform");
198    Mutex::Autolock lock(mMutex);
199    mNextTransform = transform;
200    return OK;
201}
202
203status_t SurfaceTexture::updateTexImage() {
204    LOGV("SurfaceTexture::updateTexImage");
205    Mutex::Autolock lock(mMutex);
206
207    // We always bind the texture even if we don't update its contents.
208    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
209
210    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
211    // so this check will fail until a buffer gets queued.
212    if (mCurrentTexture != mLastQueued) {
213        // Update the GL texture object.
214        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
215        if (image == EGL_NO_IMAGE_KHR) {
216            EGLDisplay dpy = eglGetCurrentDisplay();
217            sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
218            image = createImage(dpy, graphicBuffer);
219            mSlots[mLastQueued].mEglImage = image;
220            mSlots[mLastQueued].mEglDisplay = dpy;
221        }
222        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
223        GLint error = glGetError();
224        if (error != GL_NO_ERROR) {
225            LOGE("error binding external texture image %p (slot %d): %#04x",
226                    image, mLastQueued, error);
227            return -EINVAL;
228        }
229
230        // Update the SurfaceTexture state.
231        mCurrentTexture = mLastQueued;
232        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
233        mCurrentCrop = mLastQueuedCrop;
234        mCurrentTransform = mLastQueuedTransform;
235    }
236    return OK;
237}
238
239void SurfaceTexture::getTransformMatrix(float mtx[16]) {
240    LOGV("SurfaceTexture::updateTexImage");
241    Mutex::Autolock lock(mMutex);
242
243    float xform[16];
244    for (int i = 0; i < 16; i++) {
245        xform[i] = mtxIdentity[i];
246    }
247    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
248        float result[16];
249        mtxMul(result, xform, mtxFlipH);
250        for (int i = 0; i < 16; i++) {
251            xform[i] = result[i];
252        }
253    }
254    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
255        float result[16];
256        mtxMul(result, xform, mtxFlipV);
257        for (int i = 0; i < 16; i++) {
258            xform[i] = result[i];
259        }
260    }
261    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
262        float result[16];
263        mtxMul(result, xform, mtxRot90);
264        for (int i = 0; i < 16; i++) {
265            xform[i] = result[i];
266        }
267    }
268
269    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
270    float tx, ty, sx, sy;
271    if (!mCurrentCrop.isEmpty()) {
272        tx = float(mCurrentCrop.left) / float(buf->getWidth());
273        ty = float(buf->getHeight() - mCurrentCrop.bottom) /
274                float(buf->getHeight());
275        sx = float(mCurrentCrop.width()) / float(buf->getWidth());
276        sy = float(mCurrentCrop.height()) / float(buf->getHeight());
277    } else {
278        tx = 0.0f;
279        ty = 0.0f;
280        sx = 1.0f;
281        sy = 1.0f;
282    }
283    float crop[16] = {
284        sx, 0, 0, 0,
285        0, sy, 0, 0,
286        0, 0, 1, 0,
287        sx*tx, sy*ty, 0, 1,
288    };
289
290    float mtxBeforeFlipV[16];
291    mtxMul(mtxBeforeFlipV, crop, xform);
292
293    // SurfaceFlinger expects the top of its window textures to be at a Y
294    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
295    // want to expose this to applications, however, so we must add an
296    // additional vertical flip to the transform after all the other transforms.
297    mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
298}
299
300void SurfaceTexture::setFrameAvailableListener(
301        const sp<FrameAvailableListener>& l) {
302    LOGV("SurfaceTexture::setFrameAvailableListener");
303    Mutex::Autolock lock(mMutex);
304    mFrameAvailableListener = l;
305}
306
307void SurfaceTexture::freeAllBuffers() {
308    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
309        mSlots[i].mGraphicBuffer = 0;
310        mSlots[i].mOwnedByClient = false;
311        if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
312            eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
313            mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
314            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
315        }
316    }
317
318    int exceptBuf = -1;
319    for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
320        if (mAllocdBuffers[i] == mCurrentTextureBuf) {
321            exceptBuf = i;
322            break;
323        }
324    }
325    mAllocdBuffers.clear();
326    if (exceptBuf >= 0) {
327        mAllocdBuffers.add(mCurrentTextureBuf);
328    }
329    mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
330}
331
332EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
333        const sp<GraphicBuffer>& graphicBuffer) {
334    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
335    EGLint attrs[] = {
336        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
337        EGL_NONE,
338    };
339    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
340            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
341    EGLint error = eglGetError();
342    if (error != EGL_SUCCESS) {
343        LOGE("error creating EGLImage: %#x", error);
344    } else if (image == EGL_NO_IMAGE_KHR) {
345        LOGE("no error reported, but no image was returned by "
346                "eglCreateImageKHR");
347    }
348    return image;
349}
350
351static void mtxMul(float out[16], const float a[16], const float b[16]) {
352    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
353    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
354    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
355    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
356
357    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
358    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
359    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
360    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
361
362    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
363    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
364    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
365    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
366
367    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
368    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
369    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
370    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
371}
372
373}; // namespace android
374