SurfaceTexture.h revision 86edf4f6470ee0f108bf40d3c1d23bf0a78c9c38
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#ifndef ANDROID_GUI_SURFACETEXTURE_H
18#define ANDROID_GUI_SURFACETEXTURE_H
19
20#include <EGL/egl.h>
21#include <EGL/eglext.h>
22#include <GLES2/gl2.h>
23#include <GLES2/gl2ext.h>
24
25#include <gui/ISurfaceTexture.h>
26
27#include <ui/GraphicBuffer.h>
28
29#include <utils/String8.h>
30#include <utils/Vector.h>
31#include <utils/threads.h>
32
33#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
34
35namespace android {
36// ----------------------------------------------------------------------------
37
38class IGraphicBufferAlloc;
39class String8;
40
41class SurfaceTexture : public BnSurfaceTexture {
42public:
43    enum { MIN_UNDEQUEUED_BUFFERS = 2 };
44    enum {
45        MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
46        MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS
47    };
48    enum { NUM_BUFFER_SLOTS = 32 };
49    enum { NO_CONNECTED_API = 0 };
50
51    struct FrameAvailableListener : public virtual RefBase {
52        // onFrameAvailable() is called from queueBuffer() each time an
53        // additional frame becomes available for consumption. This means that
54        // frames that are queued while in asynchronous mode only trigger the
55        // callback if no previous frames are pending. Frames queued while in
56        // synchronous mode always trigger the callback.
57        //
58        // This is called without any lock held and can be called concurrently
59        // by multiple threads.
60        virtual void onFrameAvailable() = 0;
61    };
62
63    // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
64    // name of the OpenGL ES texture to which images are to be streamed. This
65    // texture name cannot be changed once the SurfaceTexture is created.
66    // allowSynchronousMode specifies whether or not synchronous mode can be
67    // enabled. texTarget specifies the OpenGL ES texture target to which the
68    // texture will be bound in updateTexImage. useFenceSync specifies whether
69    // fences should be used to synchronize access to buffers if that behavior
70    // is enabled at compile-time.
71    SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
72            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true);
73
74    virtual ~SurfaceTexture();
75
76    // setBufferCount updates the number of available buffer slots.  After
77    // calling this all buffer slots are both unallocated and owned by the
78    // SurfaceTexture object (i.e. they are not owned by the client).
79    virtual status_t setBufferCount(int bufferCount);
80
81    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
82
83    // dequeueBuffer gets the next buffer slot index for the client to use. If a
84    // buffer slot is available then that slot index is written to the location
85    // pointed to by the buf argument and a status of OK is returned.  If no
86    // slot is available then a status of -EBUSY is returned and buf is
87    // unmodified.
88    // The width and height parameters must be no greater than the minimum of
89    // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
90    // An error due to invalid dimensions might not be reported until
91    // updateTexImage() is called.
92    virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
93            uint32_t format, uint32_t usage);
94
95    // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
96    // timestamp must be provided for the buffer. The timestamp is in
97    // nanoseconds, and must be monotonically increasing. Its other semantics
98    // (zero point, etc) are client-dependent and should be documented by the
99    // client.
100    virtual status_t queueBuffer(int buf, int64_t timestamp,
101            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
102    virtual void cancelBuffer(int buf);
103    virtual status_t setCrop(const Rect& reg);
104    virtual status_t setTransform(uint32_t transform);
105    virtual status_t setScalingMode(int mode);
106
107    virtual int query(int what, int* value);
108
109    // setSynchronousMode set whether dequeueBuffer is synchronous or
110    // asynchronous. In synchronous mode, dequeueBuffer blocks until
111    // a buffer is available, the currently bound buffer can be dequeued and
112    // queued buffers will be retired in order.
113    // The default mode is asynchronous.
114    virtual status_t setSynchronousMode(bool enabled);
115
116    // connect attempts to connect a client API to the SurfaceTexture.  This
117    // must be called before any other ISurfaceTexture methods are called except
118    // for getAllocator.
119    //
120    // This method will fail if the connect was previously called on the
121    // SurfaceTexture and no corresponding disconnect call was made.
122    virtual status_t connect(int api,
123            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
124
125    // disconnect attempts to disconnect a client API from the SurfaceTexture.
126    // Calling this method will cause any subsequent calls to other
127    // ISurfaceTexture methods to fail except for getAllocator and connect.
128    // Successfully calling connect after this will allow the other methods to
129    // succeed again.
130    //
131    // This method will fail if the the SurfaceTexture is not currently
132    // connected to the specified client API.
133    virtual status_t disconnect(int api);
134
135    // updateTexImage sets the image contents of the target texture to that of
136    // the most recently queued buffer.
137    //
138    // This call may only be made while the OpenGL ES context to which the
139    // target texture belongs is bound to the calling thread.
140    status_t updateTexImage();
141
142    // setBufferCountServer set the buffer count. If the client has requested
143    // a buffer count using setBufferCount, the server-buffer count will
144    // take effect once the client sets the count back to zero.
145    status_t setBufferCountServer(int bufferCount);
146
147    // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
148    // associated with the texture image set by the most recent call to
149    // updateTexImage.
150    //
151    // This transform matrix maps 2D homogeneous texture coordinates of the form
152    // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
153    // coordinate that should be used to sample that location from the texture.
154    // Sampling the texture outside of the range of this transform is undefined.
155    //
156    // This transform is necessary to compensate for transforms that the stream
157    // content producer may implicitly apply to the content. By forcing users of
158    // a SurfaceTexture to apply this transform we avoid performing an extra
159    // copy of the data that would be needed to hide the transform from the
160    // user.
161    //
162    // The matrix is stored in column-major order so that it may be passed
163    // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
164    // functions.
165    void getTransformMatrix(float mtx[16]);
166
167    // getTimestamp retrieves the timestamp associated with the texture image
168    // set by the most recent call to updateTexImage.
169    //
170    // The timestamp is in nanoseconds, and is monotonically increasing. Its
171    // other semantics (zero point, etc) are source-dependent and should be
172    // documented by the source.
173    int64_t getTimestamp();
174
175    // setFrameAvailableListener sets the listener object that will be notified
176    // when a new frame becomes available.
177    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
178
179    // getAllocator retrieves the binder object that must be referenced as long
180    // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
181    // Holding this binder reference prevents SurfaceFlinger from freeing the
182    // buffers before the client is done with them.
183    sp<IBinder> getAllocator();
184
185    // setDefaultBufferSize is used to set the size of buffers returned by
186    // requestBuffers when a with and height of zero is requested.
187    // A call to setDefaultBufferSize() may trigger requestBuffers() to
188    // be called from the client.
189    // The width and height parameters must be no greater than the minimum of
190    // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
191    // An error due to invalid dimensions might not be reported until
192    // updateTexImage() is called.
193    status_t setDefaultBufferSize(uint32_t width, uint32_t height);
194
195    // getCurrentBuffer returns the buffer associated with the current image.
196    sp<GraphicBuffer> getCurrentBuffer() const;
197
198    // getCurrentTextureTarget returns the texture target of the current
199    // texture as returned by updateTexImage().
200    GLenum getCurrentTextureTarget() const;
201
202    // getCurrentCrop returns the cropping rectangle of the current buffer
203    Rect getCurrentCrop() const;
204
205    // getCurrentTransform returns the transform of the current buffer
206    uint32_t getCurrentTransform() const;
207
208    // getCurrentScalingMode returns the scaling mode of the current buffer
209    uint32_t getCurrentScalingMode() const;
210
211    // isSynchronousMode returns whether the SurfaceTexture is currently in
212    // synchronous mode.
213    bool isSynchronousMode() const;
214
215    // abandon frees all the buffers and puts the SurfaceTexture into the
216    // 'abandoned' state.  Once put in this state the SurfaceTexture can never
217    // leave it.  When in the 'abandoned' state, all methods of the
218    // ISurfaceTexture interface will fail with the NO_INIT error.
219    //
220    // Note that while calling this method causes all the buffers to be freed
221    // from the perspective of the the SurfaceTexture, if there are additional
222    // references on the buffers (e.g. if a buffer is referenced by a client or
223    // by OpenGL ES as a texture) then those buffer will remain allocated.
224    void abandon();
225
226    // set the name of the SurfaceTexture that will be used to identify it in
227    // log messages.
228    void setName(const String8& name);
229
230    // dump our state in a String
231    void dump(String8& result) const;
232    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
233
234protected:
235
236    // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
237    // for the given slot.
238    void freeBufferLocked(int index);
239
240    // freeAllBuffersLocked frees the resources (both GraphicBuffer and
241    // EGLImage) for all slots.
242    void freeAllBuffersLocked();
243
244    // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
245    // and EGLImage) for all slots except the head of mQueue
246    void freeAllBuffersExceptHeadLocked();
247
248    // drainQueueLocked drains the buffer queue if we're in synchronous mode
249    // returns immediately otherwise. return NO_INIT if SurfaceTexture
250    // became abandoned or disconnected during this call.
251    status_t drainQueueLocked();
252
253    // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
254    // synchronous mode and free all buffers. In asynchronous mode, all buffers
255    // are freed except the current buffer.
256    status_t drainQueueAndFreeBuffersLocked();
257
258    static bool isExternalFormat(uint32_t format);
259
260private:
261
262    // createImage creates a new EGLImage from a GraphicBuffer.
263    EGLImageKHR createImage(EGLDisplay dpy,
264            const sp<GraphicBuffer>& graphicBuffer);
265
266    status_t setBufferCountServerLocked(int bufferCount);
267
268    // computeCurrentTransformMatrix computes the transform matrix for the
269    // current texture.  It uses mCurrentTransform and the current GraphicBuffer
270    // to compute this matrix and stores it in mCurrentTransformMatrix.
271    void computeCurrentTransformMatrix();
272
273    enum { INVALID_BUFFER_SLOT = -1 };
274
275    struct BufferSlot {
276
277        BufferSlot()
278            : mEglImage(EGL_NO_IMAGE_KHR),
279              mEglDisplay(EGL_NO_DISPLAY),
280              mBufferState(BufferSlot::FREE),
281              mRequestBufferCalled(false),
282              mTransform(0),
283              mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
284              mTimestamp(0),
285              mFrameNumber(0),
286              mFence(EGL_NO_SYNC_KHR) {
287            mCrop.makeInvalid();
288        }
289
290        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
291        // if no buffer has been allocated.
292        sp<GraphicBuffer> mGraphicBuffer;
293
294        // mEglImage is the EGLImage created from mGraphicBuffer.
295        EGLImageKHR mEglImage;
296
297        // mEglDisplay is the EGLDisplay used to create mEglImage.
298        EGLDisplay mEglDisplay;
299
300        // BufferState represents the different states in which a buffer slot
301        // can be.
302        enum BufferState {
303            // FREE indicates that the buffer is not currently being used and
304            // will not be used in the future until it gets dequeued and
305            // subsequently queued by the client.
306            FREE = 0,
307
308            // DEQUEUED indicates that the buffer has been dequeued by the
309            // client, but has not yet been queued or canceled. The buffer is
310            // considered 'owned' by the client, and the server should not use
311            // it for anything.
312            //
313            // Note that when in synchronous-mode (mSynchronousMode == true),
314            // the buffer that's currently attached to the texture may be
315            // dequeued by the client.  That means that the current buffer can
316            // be in either the DEQUEUED or QUEUED state.  In asynchronous mode,
317            // however, the current buffer is always in the QUEUED state.
318            DEQUEUED = 1,
319
320            // QUEUED indicates that the buffer has been queued by the client,
321            // and has not since been made available for the client to dequeue.
322            // Attaching the buffer to the texture does NOT transition the
323            // buffer away from the QUEUED state. However, in Synchronous mode
324            // the current buffer may be dequeued by the client under some
325            // circumstances. See the note about the current buffer in the
326            // documentation for DEQUEUED.
327            QUEUED = 2,
328        };
329
330        // mBufferState is the current state of this buffer slot.
331        BufferState mBufferState;
332
333        // mRequestBufferCalled is used for validating that the client did
334        // call requestBuffer() when told to do so. Technically this is not
335        // needed but useful for debugging and catching client bugs.
336        bool mRequestBufferCalled;
337
338        // mCrop is the current crop rectangle for this buffer slot. This gets
339        // set to mNextCrop each time queueBuffer gets called for this buffer.
340        Rect mCrop;
341
342        // mTransform is the current transform flags for this buffer slot. This
343        // gets set to mNextTransform each time queueBuffer gets called for this
344        // slot.
345        uint32_t mTransform;
346
347        // mScalingMode is the current scaling mode for this buffer slot. This
348        // gets set to mNextScalingMode each time queueBuffer gets called for
349        // this slot.
350        uint32_t mScalingMode;
351
352        // mTimestamp is the current timestamp for this buffer slot. This gets
353        // to set by queueBuffer each time this slot is queued.
354        int64_t mTimestamp;
355
356        // mFrameNumber is the number of the queued frame for this slot.
357        uint64_t mFrameNumber;
358
359        // mFence is the EGL sync object that must signal before the buffer
360        // associated with this buffer slot may be dequeued. It is initialized
361        // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
362        // on a compile-time option) set to a new sync object in updateTexImage.
363        EGLSyncKHR mFence;
364    };
365
366    // mSlots is the array of buffer slots that must be mirrored on the client
367    // side. This allows buffer ownership to be transferred between the client
368    // and server without sending a GraphicBuffer over binder. The entire array
369    // is initialized to NULL at construction time, and buffers are allocated
370    // for a slot when requestBuffer is called with that slot's index.
371    BufferSlot mSlots[NUM_BUFFER_SLOTS];
372
373    // mDefaultWidth holds the default width of allocated buffers. It is used
374    // in requestBuffers() if a width and height of zero is specified.
375    uint32_t mDefaultWidth;
376
377    // mDefaultHeight holds the default height of allocated buffers. It is used
378    // in requestBuffers() if a width and height of zero is specified.
379    uint32_t mDefaultHeight;
380
381    // mPixelFormat holds the pixel format of allocated buffers. It is used
382    // in requestBuffers() if a format of zero is specified.
383    uint32_t mPixelFormat;
384
385    // mBufferCount is the number of buffer slots that the client and server
386    // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
387    // by calling setBufferCount or setBufferCountServer
388    int mBufferCount;
389
390    // mClientBufferCount is the number of buffer slots requested by the client.
391    // The default is zero, which means the client doesn't care how many buffers
392    // there is.
393    int mClientBufferCount;
394
395    // mServerBufferCount buffer count requested by the server-side
396    int mServerBufferCount;
397
398    // mCurrentTexture is the buffer slot index of the buffer that is currently
399    // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
400    // indicating that no buffer slot is currently bound to the texture. Note,
401    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
402    // that no buffer is bound to the texture. A call to setBufferCount will
403    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
404    int mCurrentTexture;
405
406    // mCurrentTextureBuf is the graphic buffer of the current texture. It's
407    // possible that this buffer is not associated with any buffer slot, so we
408    // must track it separately in order to support the getCurrentBuffer method.
409    sp<GraphicBuffer> mCurrentTextureBuf;
410
411    // mCurrentCrop is the crop rectangle that applies to the current texture.
412    // It gets set each time updateTexImage is called.
413    Rect mCurrentCrop;
414
415    // mCurrentTransform is the transform identifier for the current texture. It
416    // gets set each time updateTexImage is called.
417    uint32_t mCurrentTransform;
418
419    // mCurrentScalingMode is the scaling mode for the current texture. It gets
420    // set to each time updateTexImage is called.
421    uint32_t mCurrentScalingMode;
422
423    // mCurrentTransformMatrix is the transform matrix for the current texture.
424    // It gets computed by computeTransformMatrix each time updateTexImage is
425    // called.
426    float mCurrentTransformMatrix[16];
427
428    // mCurrentTimestamp is the timestamp for the current texture. It
429    // gets set each time updateTexImage is called.
430    int64_t mCurrentTimestamp;
431
432    // mNextCrop is the crop rectangle that will be used for the next buffer
433    // that gets queued. It is set by calling setCrop.
434    Rect mNextCrop;
435
436    // mNextTransform is the transform identifier that will be used for the next
437    // buffer that gets queued. It is set by calling setTransform.
438    uint32_t mNextTransform;
439
440    // mNextScalingMode is the scaling mode that will be used for the next
441    // buffers that get queued. It is set by calling setScalingMode.
442    int mNextScalingMode;
443
444    // mTexName is the name of the OpenGL texture to which streamed images will
445    // be bound when updateTexImage is called. It is set at construction time
446    // changed with a call to setTexName.
447    const GLuint mTexName;
448
449    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
450    // allocate new GraphicBuffer objects.
451    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
452
453    // mFrameAvailableListener is the listener object that will be called when a
454    // new frame becomes available. If it is not NULL it will be called from
455    // queueBuffer.
456    sp<FrameAvailableListener> mFrameAvailableListener;
457
458    // mSynchronousMode whether we're in synchronous mode or not
459    bool mSynchronousMode;
460
461    // mAllowSynchronousMode whether we allow synchronous mode or not
462    const bool mAllowSynchronousMode;
463
464    // mConnectedApi indicates the API that is currently connected to this
465    // SurfaceTexture.  It defaults to NO_CONNECTED_API (= 0), and gets updated
466    // by the connect and disconnect methods.
467    int mConnectedApi;
468
469    // mDequeueCondition condition used for dequeueBuffer in synchronous mode
470    mutable Condition mDequeueCondition;
471
472    // mQueue is a FIFO of queued buffers used in synchronous mode
473    typedef Vector<int> Fifo;
474    Fifo mQueue;
475
476    // mAbandoned indicates that the SurfaceTexture will no longer be used to
477    // consume images buffers pushed to it using the ISurfaceTexture interface.
478    // It is initialized to false, and set to true in the abandon method.  A
479    // SurfaceTexture that has been abandoned will return the NO_INIT error from
480    // all ISurfaceTexture methods capable of returning an error.
481    bool mAbandoned;
482
483    // mName is a string used to identify the SurfaceTexture in log messages.
484    // It is set by the setName method.
485    String8 mName;
486
487    // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
488    // extension should be used to prevent buffers from being dequeued before
489    // it's safe for them to be written. It gets set at construction time and
490    // never changes.
491    const bool mUseFenceSync;
492
493    // mMutex is the mutex used to prevent concurrent access to the member
494    // variables of SurfaceTexture objects. It must be locked whenever the
495    // member variables are accessed.
496    mutable Mutex mMutex;
497
498    // mTexTarget is the GL texture target with which the GL texture object is
499    // associated.  It is set in the constructor and never changed.  It is
500    // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
501    // Browser.  In that case it is set to GL_TEXTURE_2D to allow
502    // glCopyTexSubImage to read from the texture.  This is a hack to work
503    // around a GL driver limitation on the number of FBO attachments, which the
504    // browser's tile cache exceeds.
505    const GLenum mTexTarget;
506
507    // mFrameCounter is the free running counter, incremented for every buffer queued
508    // with the surface Texture.
509    uint64_t mFrameCounter;
510
511
512};
513
514// ----------------------------------------------------------------------------
515}; // namespace android
516
517#endif // ANDROID_GUI_SURFACETEXTURE_H
518