| Daniel Lam | 6b091c5 | 2012-01-22 15:26:27 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2012 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_BUFFERQUEUE_H | 
|  | 18 | #define ANDROID_GUI_BUFFERQUEUE_H | 
|  | 19 |  | 
|  | 20 | #include <EGL/egl.h> | 
|  | 21 |  | 
|  | 22 | #include <gui/ISurfaceTexture.h> | 
|  | 23 |  | 
|  | 24 | #include <surfaceflinger/IGraphicBufferAlloc.h> | 
|  | 25 | #include <ui/GraphicBuffer.h> | 
|  | 26 |  | 
|  | 27 | #include <utils/String8.h> | 
|  | 28 | #include <utils/Vector.h> | 
|  | 29 | #include <utils/threads.h> | 
|  | 30 |  | 
|  | 31 | namespace android { | 
|  | 32 | // ---------------------------------------------------------------------------- | 
|  | 33 |  | 
|  | 34 | class BufferQueue : public BnSurfaceTexture { | 
|  | 35 | public: | 
|  | 36 | enum { MIN_UNDEQUEUED_BUFFERS = 2 }; | 
|  | 37 | enum { | 
|  | 38 | MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1, | 
|  | 39 | MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS | 
|  | 40 | }; | 
|  | 41 | enum { NUM_BUFFER_SLOTS = 32 }; | 
|  | 42 | enum { NO_CONNECTED_API = 0 }; | 
|  | 43 |  | 
|  | 44 | struct FrameAvailableListener : public virtual RefBase { | 
|  | 45 | // onFrameAvailable() is called from queueBuffer() each time an | 
|  | 46 | // additional frame becomes available for consumption. This means that | 
|  | 47 | // frames that are queued while in asynchronous mode only trigger the | 
|  | 48 | // callback if no previous frames are pending. Frames queued while in | 
|  | 49 | // synchronous mode always trigger the callback. | 
|  | 50 | // | 
|  | 51 | // This is called without any lock held and can be called concurrently | 
|  | 52 | // by multiple threads. | 
|  | 53 | virtual void onFrameAvailable() = 0; | 
|  | 54 | }; | 
|  | 55 |  | 
|  | 56 | // BufferQueue manages a pool of gralloc memory slots to be used | 
|  | 57 | // by producers and consumers. | 
|  | 58 | // allowSynchronousMode specifies whether or not synchronous mode can be | 
|  | 59 | // enabled. | 
|  | 60 | BufferQueue(bool allowSynchronousMode = true); | 
|  | 61 | virtual ~BufferQueue(); | 
|  | 62 |  | 
| Daniel Lam | b856052 | 2012-01-30 15:51:27 -0800 | [diff] [blame] | 63 | virtual int query(int what, int* value); | 
|  | 64 |  | 
| Daniel Lam | 6b091c5 | 2012-01-22 15:26:27 -0800 | [diff] [blame] | 65 | // setBufferCount updates the number of available buffer slots.  After | 
|  | 66 | // calling this all buffer slots are both unallocated and owned by the | 
|  | 67 | // BufferQueue object (i.e. they are not owned by the client). | 
|  | 68 | virtual status_t setBufferCount(int bufferCount); | 
|  | 69 |  | 
|  | 70 | virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); | 
|  | 71 |  | 
|  | 72 | // dequeueBuffer gets the next buffer slot index for the client to use. If a | 
|  | 73 | // buffer slot is available then that slot index is written to the location | 
|  | 74 | // pointed to by the buf argument and a status of OK is returned.  If no | 
|  | 75 | // slot is available then a status of -EBUSY is returned and buf is | 
|  | 76 | // unmodified. | 
|  | 77 | // The width and height parameters must be no greater than the minimum of | 
|  | 78 | // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). | 
|  | 79 | // An error due to invalid dimensions might not be reported until | 
|  | 80 | // updateTexImage() is called. | 
|  | 81 | virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height, | 
|  | 82 | uint32_t format, uint32_t usage); | 
|  | 83 |  | 
|  | 84 | // queueBuffer returns a filled buffer to the BufferQueue. In addition, a | 
|  | 85 | // timestamp must be provided for the buffer. The timestamp is in | 
|  | 86 | // nanoseconds, and must be monotonically increasing. Its other semantics | 
|  | 87 | // (zero point, etc) are client-dependent and should be documented by the | 
|  | 88 | // client. | 
|  | 89 | virtual status_t queueBuffer(int buf, int64_t timestamp, | 
|  | 90 | uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); | 
|  | 91 | virtual void cancelBuffer(int buf); | 
|  | 92 | virtual status_t setCrop(const Rect& reg); | 
|  | 93 | virtual status_t setTransform(uint32_t transform); | 
|  | 94 | virtual status_t setScalingMode(int mode); | 
|  | 95 |  | 
|  | 96 | // setSynchronousMode set whether dequeueBuffer is synchronous or | 
|  | 97 | // asynchronous. In synchronous mode, dequeueBuffer blocks until | 
|  | 98 | // a buffer is available, the currently bound buffer can be dequeued and | 
|  | 99 | // queued buffers will be retired in order. | 
|  | 100 | // The default mode is asynchronous. | 
|  | 101 | virtual status_t setSynchronousMode(bool enabled); | 
|  | 102 |  | 
|  | 103 | // connect attempts to connect a producer client API to the BufferQueue. | 
|  | 104 | // This must be called before any other ISurfaceTexture methods are called | 
|  | 105 | // except for getAllocator. | 
|  | 106 | // | 
|  | 107 | // This method will fail if the connect was previously called on the | 
|  | 108 | // BufferQueue and no corresponding disconnect call was made. | 
|  | 109 | virtual status_t connect(int api, | 
|  | 110 | uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); | 
|  | 111 |  | 
|  | 112 | // disconnect attempts to disconnect a producer client API from the | 
|  | 113 | // BufferQueue. Calling this method will cause any subsequent calls to other | 
|  | 114 | // ISurfaceTexture methods to fail except for getAllocator and connect. | 
|  | 115 | // Successfully calling connect after this will allow the other methods to | 
|  | 116 | // succeed again. | 
|  | 117 | // | 
|  | 118 | // This method will fail if the the BufferQueue is not currently | 
|  | 119 | // connected to the specified client API. | 
|  | 120 | virtual status_t disconnect(int api); | 
|  | 121 |  | 
|  | 122 | protected: | 
|  | 123 |  | 
|  | 124 | // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage) | 
|  | 125 | // for the given slot. | 
|  | 126 | void freeBufferLocked(int index); | 
|  | 127 |  | 
|  | 128 | // freeAllBuffersLocked frees the resources (both GraphicBuffer and | 
|  | 129 | // EGLImage) for all slots. | 
|  | 130 | void freeAllBuffersLocked(); | 
|  | 131 |  | 
|  | 132 | // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer | 
|  | 133 | // and EGLImage) for all slots except the head of mQueue | 
|  | 134 | void freeAllBuffersExceptHeadLocked(); | 
|  | 135 |  | 
|  | 136 | // drainQueueLocked drains the buffer queue if we're in synchronous mode | 
|  | 137 | // returns immediately otherwise. It returns NO_INIT if the BufferQueue | 
|  | 138 | // became abandoned or disconnected during this call. | 
|  | 139 | status_t drainQueueLocked(); | 
|  | 140 |  | 
|  | 141 | // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in | 
|  | 142 | // synchronous mode and free all buffers. In asynchronous mode, all buffers | 
|  | 143 | // are freed except the current buffer. | 
|  | 144 | status_t drainQueueAndFreeBuffersLocked(); | 
|  | 145 |  | 
|  | 146 | status_t setBufferCountServerLocked(int bufferCount); | 
|  | 147 |  | 
|  | 148 | enum { INVALID_BUFFER_SLOT = -1 }; | 
|  | 149 |  | 
|  | 150 | struct BufferSlot { | 
|  | 151 |  | 
|  | 152 | BufferSlot() | 
|  | 153 | : mEglImage(EGL_NO_IMAGE_KHR), | 
|  | 154 | mEglDisplay(EGL_NO_DISPLAY), | 
|  | 155 | mBufferState(BufferSlot::FREE), | 
|  | 156 | mRequestBufferCalled(false), | 
|  | 157 | mTransform(0), | 
|  | 158 | mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), | 
|  | 159 | mTimestamp(0), | 
|  | 160 | mFrameNumber(0), | 
|  | 161 | mFence(EGL_NO_SYNC_KHR) { | 
|  | 162 | mCrop.makeInvalid(); | 
|  | 163 | } | 
|  | 164 |  | 
|  | 165 | // mGraphicBuffer points to the buffer allocated for this slot or is NULL | 
|  | 166 | // if no buffer has been allocated. | 
|  | 167 | sp<GraphicBuffer> mGraphicBuffer; | 
|  | 168 |  | 
|  | 169 | // mEglImage is the EGLImage created from mGraphicBuffer. | 
|  | 170 | EGLImageKHR mEglImage; | 
|  | 171 |  | 
|  | 172 | // mEglDisplay is the EGLDisplay used to create mEglImage. | 
|  | 173 | EGLDisplay mEglDisplay; | 
|  | 174 |  | 
|  | 175 | // BufferState represents the different states in which a buffer slot | 
|  | 176 | // can be. | 
|  | 177 | enum BufferState { | 
|  | 178 | // FREE indicates that the buffer is not currently being used and | 
|  | 179 | // will not be used in the future until it gets dequeued and | 
|  | 180 | // subsequently queued by the client. | 
|  | 181 | FREE = 0, | 
|  | 182 |  | 
|  | 183 | // DEQUEUED indicates that the buffer has been dequeued by the | 
|  | 184 | // client, but has not yet been queued or canceled. The buffer is | 
|  | 185 | // considered 'owned' by the client, and the server should not use | 
|  | 186 | // it for anything. | 
|  | 187 | // | 
|  | 188 | // Note that when in synchronous-mode (mSynchronousMode == true), | 
|  | 189 | // the buffer that's currently attached to the texture may be | 
|  | 190 | // dequeued by the client.  That means that the current buffer can | 
|  | 191 | // be in either the DEQUEUED or QUEUED state.  In asynchronous mode, | 
|  | 192 | // however, the current buffer is always in the QUEUED state. | 
|  | 193 | DEQUEUED = 1, | 
|  | 194 |  | 
|  | 195 | // QUEUED indicates that the buffer has been queued by the client, | 
|  | 196 | // and has not since been made available for the client to dequeue. | 
|  | 197 | // Attaching the buffer to the texture does NOT transition the | 
|  | 198 | // buffer away from the QUEUED state. However, in Synchronous mode | 
|  | 199 | // the current buffer may be dequeued by the client under some | 
|  | 200 | // circumstances. See the note about the current buffer in the | 
|  | 201 | // documentation for DEQUEUED. | 
|  | 202 | QUEUED = 2, | 
|  | 203 | }; | 
|  | 204 |  | 
|  | 205 | // mBufferState is the current state of this buffer slot. | 
|  | 206 | BufferState mBufferState; | 
|  | 207 |  | 
|  | 208 | // mRequestBufferCalled is used for validating that the client did | 
|  | 209 | // call requestBuffer() when told to do so. Technically this is not | 
|  | 210 | // needed but useful for debugging and catching client bugs. | 
|  | 211 | bool mRequestBufferCalled; | 
|  | 212 |  | 
|  | 213 | // mCrop is the current crop rectangle for this buffer slot. This gets | 
|  | 214 | // set to mNextCrop each time queueBuffer gets called for this buffer. | 
|  | 215 | Rect mCrop; | 
|  | 216 |  | 
|  | 217 | // mTransform is the current transform flags for this buffer slot. This | 
|  | 218 | // gets set to mNextTransform each time queueBuffer gets called for this | 
|  | 219 | // slot. | 
|  | 220 | uint32_t mTransform; | 
|  | 221 |  | 
|  | 222 | // mScalingMode is the current scaling mode for this buffer slot. This | 
|  | 223 | // gets set to mNextScalingMode each time queueBuffer gets called for | 
|  | 224 | // this slot. | 
|  | 225 | uint32_t mScalingMode; | 
|  | 226 |  | 
|  | 227 | // mTimestamp is the current timestamp for this buffer slot. This gets | 
|  | 228 | // to set by queueBuffer each time this slot is queued. | 
|  | 229 | int64_t mTimestamp; | 
|  | 230 |  | 
|  | 231 | // mFrameNumber is the number of the queued frame for this slot. | 
|  | 232 | uint64_t mFrameNumber; | 
|  | 233 |  | 
|  | 234 | // mFence is the EGL sync object that must signal before the buffer | 
|  | 235 | // associated with this buffer slot may be dequeued. It is initialized | 
|  | 236 | // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based | 
|  | 237 | // on a compile-time option) set to a new sync object in updateTexImage. | 
|  | 238 | EGLSyncKHR mFence; | 
|  | 239 | }; | 
|  | 240 |  | 
|  | 241 | // mSlots is the array of buffer slots that must be mirrored on the client | 
|  | 242 | // side. This allows buffer ownership to be transferred between the client | 
|  | 243 | // and server without sending a GraphicBuffer over binder. The entire array | 
|  | 244 | // is initialized to NULL at construction time, and buffers are allocated | 
|  | 245 | // for a slot when requestBuffer is called with that slot's index. | 
|  | 246 | BufferSlot mSlots[NUM_BUFFER_SLOTS]; | 
|  | 247 |  | 
|  | 248 |  | 
|  | 249 | // mDefaultWidth holds the default width of allocated buffers. It is used | 
|  | 250 | // in requestBuffers() if a width and height of zero is specified. | 
|  | 251 | uint32_t mDefaultWidth; | 
|  | 252 |  | 
|  | 253 | // mDefaultHeight holds the default height of allocated buffers. It is used | 
|  | 254 | // in requestBuffers() if a width and height of zero is specified. | 
|  | 255 | uint32_t mDefaultHeight; | 
|  | 256 |  | 
|  | 257 | // mPixelFormat holds the pixel format of allocated buffers. It is used | 
|  | 258 | // in requestBuffers() if a format of zero is specified. | 
|  | 259 | uint32_t mPixelFormat; | 
|  | 260 |  | 
|  | 261 | // mBufferCount is the number of buffer slots that the client and server | 
|  | 262 | // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed | 
|  | 263 | // by calling setBufferCount or setBufferCountServer | 
|  | 264 | int mBufferCount; | 
|  | 265 |  | 
|  | 266 | // mClientBufferCount is the number of buffer slots requested by the client. | 
|  | 267 | // The default is zero, which means the client doesn't care how many buffers | 
|  | 268 | // there is. | 
|  | 269 | int mClientBufferCount; | 
|  | 270 |  | 
|  | 271 | // mServerBufferCount buffer count requested by the server-side | 
|  | 272 | int mServerBufferCount; | 
|  | 273 |  | 
|  | 274 | // mCurrentTexture is the buffer slot index of the buffer that is currently | 
|  | 275 | // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT, | 
|  | 276 | // indicating that no buffer slot is currently bound to the texture. Note, | 
|  | 277 | // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean | 
|  | 278 | // that no buffer is bound to the texture. A call to setBufferCount will | 
|  | 279 | // reset mCurrentTexture to INVALID_BUFFER_SLOT. | 
|  | 280 | int mCurrentTexture; | 
|  | 281 |  | 
|  | 282 | // mNextCrop is the crop rectangle that will be used for the next buffer | 
|  | 283 | // that gets queued. It is set by calling setCrop. | 
|  | 284 | Rect mNextCrop; | 
|  | 285 |  | 
|  | 286 | // mNextTransform is the transform identifier that will be used for the next | 
|  | 287 | // buffer that gets queued. It is set by calling setTransform. | 
|  | 288 | uint32_t mNextTransform; | 
|  | 289 |  | 
|  | 290 | // mNextScalingMode is the scaling mode that will be used for the next | 
|  | 291 | // buffers that get queued. It is set by calling setScalingMode. | 
|  | 292 | int mNextScalingMode; | 
|  | 293 |  | 
|  | 294 | // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to | 
|  | 295 | // allocate new GraphicBuffer objects. | 
|  | 296 | sp<IGraphicBufferAlloc> mGraphicBufferAlloc; | 
|  | 297 |  | 
|  | 298 | // mFrameAvailableListener is the listener object that will be called when a | 
|  | 299 | // new frame becomes available. If it is not NULL it will be called from | 
|  | 300 | // queueBuffer. | 
|  | 301 | sp<FrameAvailableListener> mFrameAvailableListener; | 
|  | 302 |  | 
|  | 303 | // mSynchronousMode whether we're in synchronous mode or not | 
|  | 304 | bool mSynchronousMode; | 
|  | 305 |  | 
|  | 306 | // mAllowSynchronousMode whether we allow synchronous mode or not | 
|  | 307 | const bool mAllowSynchronousMode; | 
|  | 308 |  | 
|  | 309 | // mConnectedApi indicates the API that is currently connected to this | 
|  | 310 | // BufferQueue.  It defaults to NO_CONNECTED_API (= 0), and gets updated | 
|  | 311 | // by the connect and disconnect methods. | 
|  | 312 | int mConnectedApi; | 
|  | 313 |  | 
|  | 314 | // mDequeueCondition condition used for dequeueBuffer in synchronous mode | 
|  | 315 | mutable Condition mDequeueCondition; | 
|  | 316 |  | 
|  | 317 | // mQueue is a FIFO of queued buffers used in synchronous mode | 
|  | 318 | typedef Vector<int> Fifo; | 
|  | 319 | Fifo mQueue; | 
|  | 320 |  | 
|  | 321 | // mAbandoned indicates that the BufferQueue will no longer be used to | 
|  | 322 | // consume images buffers pushed to it using the ISurfaceTexture interface. | 
|  | 323 | // It is initialized to false, and set to true in the abandon method.  A | 
|  | 324 | // BufferQueue that has been abandoned will return the NO_INIT error from | 
|  | 325 | // all ISurfaceTexture methods capable of returning an error. | 
|  | 326 | bool mAbandoned; | 
|  | 327 |  | 
|  | 328 | // mName is a string used to identify the BufferQueue in log messages. | 
|  | 329 | // It is set by the setName method. | 
|  | 330 | String8 mName; | 
|  | 331 |  | 
|  | 332 | // mMutex is the mutex used to prevent concurrent access to the member | 
|  | 333 | // variables of BufferQueue objects. It must be locked whenever the | 
|  | 334 | // member variables are accessed. | 
|  | 335 | mutable Mutex mMutex; | 
|  | 336 |  | 
|  | 337 | // mFrameCounter is the free running counter, incremented for every buffer queued | 
|  | 338 | // with the surface Texture. | 
|  | 339 | uint64_t mFrameCounter; | 
|  | 340 | }; | 
|  | 341 |  | 
|  | 342 | // ---------------------------------------------------------------------------- | 
|  | 343 | }; // namespace android | 
|  | 344 |  | 
|  | 345 | #endif // ANDROID_GUI_BUFFERQUEUE_H |