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 35 namespace android { 36 // ---------------------------------------------------------------------------- 37 38 class IGraphicBufferAlloc; 39 class String8; 40 41 class SurfaceTexture : public BnSurfaceTexture { 42 public: 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 234 protected: 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 260 private: 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