• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CONSUMER_H
18 #define ANDROID_GUI_CONSUMER_H
19 
20 #include <EGL/egl.h>
21 #include <EGL/eglext.h>
22 
23 #include <com_android_graphics_libgui_flags.h>
24 #include <gui/BufferQueueDefs.h>
25 #include <gui/ConsumerBase.h>
26 
27 #include <ui/FenceTime.h>
28 #include <ui/GraphicBuffer.h>
29 
30 #include <utils/String8.h>
31 #include <utils/Vector.h>
32 #include <utils/threads.h>
33 
34 namespace android {
35 // ----------------------------------------------------------------------------
36 
37 
38 class String8;
39 
40 /*
41  * GLConsumer consumes buffers of graphics data from a BufferQueue,
42  * and makes them available to OpenGL as a texture.
43  *
44  * A typical usage pattern is to set up the GLConsumer with the
45  * desired options, and call updateTexImage() when a new frame is desired.
46  * If a new frame is available, the texture will be updated.  If not,
47  * the previous contents are retained.
48  *
49  * By default, the texture is attached to the GL_TEXTURE_EXTERNAL_OES
50  * texture target, in the EGL context of the first thread that calls
51  * updateTexImage().
52  *
53  * This class was previously called SurfaceTexture.
54  */
55 class GLConsumer : public ConsumerBase {
56 public:
57     enum { TEXTURE_EXTERNAL = 0x8D65 }; // GL_TEXTURE_EXTERNAL_OES
58     typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
59 
60     // GLConsumer constructs a new GLConsumer object. If the constructor with
61     // the tex parameter is used, tex indicates the name of the OpenGL ES
62     // texture to which images are to be streamed. texTarget specifies the
63     // OpenGL ES texture target to which the texture will be bound in
64     // updateTexImage. useFenceSync specifies whether fences should be used to
65     // synchronize access to buffers if that behavior is enabled at
66     // compile-time.
67     //
68     // A GLConsumer may be detached from one OpenGL ES context and then
69     // attached to a different context using the detachFromContext and
70     // attachToContext methods, respectively. The intention of these methods is
71     // purely to allow a GLConsumer to be transferred from one consumer
72     // context to another. If such a transfer is not needed there is no
73     // requirement that either of these methods be called.
74     //
75     // If the constructor with the tex parameter is used, the GLConsumer is
76     // created in a state where it is considered attached to an OpenGL ES
77     // context for the purposes of the attachToContext and detachFromContext
78     // methods. However, despite being considered "attached" to a context, the
79     // specific OpenGL ES context doesn't get latched until the first call to
80     // updateTexImage. After that point, all calls to updateTexImage must be
81     // made with the same OpenGL ES context current.
82     //
83     // If the constructor without the tex parameter is used, the GLConsumer is
84     // created in a detached state, and attachToContext must be called before
85     // calls to updateTexImage.
86     static std::tuple<sp<GLConsumer>, sp<Surface>> create(uint32_t tex, uint32_t textureTarget,
87                                                           bool useFenceSync,
88                                                           bool isControlledByApp);
89     static std::tuple<sp<GLConsumer>, sp<Surface>> create(uint32_t textureTarget, bool useFenceSync,
90                                                           bool isControlledByApp);
91     static sp<GLConsumer> create(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
92                                  uint32_t textureTarget, bool useFenceSync, bool isControlledByApp)
93             __attribute((deprecated(
94                     "Prefer create functions that create their own surface and consumer.")));
95     static sp<GLConsumer> create(const sp<IGraphicBufferConsumer>& bq, uint32_t textureTarget,
96                                  bool useFenceSync, bool isControlledByApp)
97             __attribute((deprecated(
98                     "Prefer create functions that create their own surface and consumer.")));
99 
100 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
101     GLConsumer(uint32_t tex, uint32_t textureTarget, bool useFenceSync, bool isControlledByApp);
102 
103     GLConsumer(uint32_t textureTarget, bool useFenceSync, bool isControlledByApp);
104 
105     GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t textureTarget,
106                bool useFenceSync, bool isControlledByApp)
107             __attribute((deprecated("Prefer ctors that create their own surface and consumer.")));
108 
109     GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t textureTarget, bool useFenceSync,
110                bool isControlledByApp)
111             __attribute((deprecated("Prefer ctors that create their own surface and consumer.")));
112 #else
113     GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t textureTarget,
114                bool useFenceSync, bool isControlledByApp);
115 
116     GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t textureTarget, bool useFenceSync,
117                bool isControlledByApp);
118 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
119 
120     // updateTexImage acquires the most recently queued buffer, and sets the
121     // image contents of the target texture to it.
122     //
123     // This call may only be made while the OpenGL ES context to which the
124     // target texture belongs is bound to the calling thread.
125     //
126     // This calls doGLFenceWait to ensure proper synchronization.
127     status_t updateTexImage();
128 
129     // releaseTexImage releases the texture acquired in updateTexImage().
130     // This is intended to be used in single buffer mode.
131     //
132     // This call may only be made while the OpenGL ES context to which the
133     // target texture belongs is bound to the calling thread.
134     status_t releaseTexImage();
135 
136     // setReleaseFence stores a fence that will signal when the current buffer
137     // is no longer being read. This fence will be returned to the producer
138     // when the current buffer is released by updateTexImage(). Multiple
139     // fences can be set for a given buffer; they will be merged into a single
140     // union fence.
141     virtual void setReleaseFence(const sp<Fence>& fence);
142 
143     // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
144     // associated with the texture image set by the most recent call to
145     // updateTexImage.
146     //
147     // This transform matrix maps 2D homogeneous texture coordinates of the form
148     // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
149     // coordinate that should be used to sample that location from the texture.
150     // Sampling the texture outside of the range of this transform is undefined.
151     //
152     // This transform is necessary to compensate for transforms that the stream
153     // content producer may implicitly apply to the content. By forcing users of
154     // a GLConsumer to apply this transform we avoid performing an extra
155     // copy of the data that would be needed to hide the transform from the
156     // user.
157     //
158     // The matrix is stored in column-major order so that it may be passed
159     // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
160     // functions.
161     void getTransformMatrix(float mtx[16]);
162 
163     // Computes the transform matrix documented by getTransformMatrix
164     // from the BufferItem sub parts.
165     static void computeTransformMatrix(float outTransform[16],
166             const sp<GraphicBuffer>& buf, const Rect& cropRect,
167             uint32_t transform, bool filtering);
168 
169     static void computeTransformMatrix(float outTransform[16], float bufferWidth,
170                                        float bufferHeight, PixelFormat pixelFormat,
171                                        const Rect& cropRect, uint32_t transform, bool filtering);
172 
173     // Scale the crop down horizontally or vertically such that it has the
174     // same aspect ratio as the buffer does.
175     static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth,
176             uint32_t bufferHeight);
177 
178     // getTimestamp retrieves the timestamp associated with the texture image
179     // set by the most recent call to updateTexImage.
180     //
181     // The timestamp is in nanoseconds, and is monotonically increasing. Its
182     // other semantics (zero point, etc) are source-dependent and should be
183     // documented by the source.
184     int64_t getTimestamp();
185 
186     // getDataSpace retrieves the DataSpace associated with the texture image
187     // set by the most recent call to updateTexImage.
188     android_dataspace getCurrentDataSpace();
189 
190     // getFrameNumber retrieves the frame number associated with the texture
191     // image set by the most recent call to updateTexImage.
192     //
193     // The frame number is an incrementing counter set to 0 at the creation of
194     // the BufferQueue associated with this consumer.
195     uint64_t getFrameNumber();
196 
197     // setDefaultBufferSize is used to set the size of buffers returned by
198     // requestBuffers when a with and height of zero is requested.
199     // A call to setDefaultBufferSize() may trigger requestBuffers() to
200     // be called from the client.
201     // The width and height parameters must be no greater than the minimum of
202     // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
203     // An error due to invalid dimensions might not be reported until
204     // updateTexImage() is called.
205     status_t setDefaultBufferSize(uint32_t width, uint32_t height);
206 
207     // setFilteringEnabled sets whether the transform matrix should be computed
208     // for use with bilinear filtering.
209     void setFilteringEnabled(bool enabled);
210 
211     // getCurrentBuffer returns the buffer associated with the current image.
212     // When outSlot is not nullptr, the current buffer slot index is also
213     // returned.
214     sp<GraphicBuffer> getCurrentBuffer(int* outSlot = nullptr) const;
215 
216     // getCurrentTextureTarget returns the texture target of the current
217     // texture as returned by updateTexImage().
218     uint32_t getCurrentTextureTarget() const;
219 
220     // getCurrentCrop returns the cropping rectangle of the current buffer.
221     Rect getCurrentCrop() const;
222 
223     // getCurrentTransform returns the transform of the current buffer.
224     uint32_t getCurrentTransform() const;
225 
226     // getCurrentScalingMode returns the scaling mode of the current buffer.
227     uint32_t getCurrentScalingMode() const;
228 
229     // getCurrentFence returns the fence indicating when the current buffer is
230     // ready to be read from.
231     sp<Fence> getCurrentFence() const;
232 
233     // getCurrentFence returns the FenceTime indicating when the current
234     // buffer is ready to be read from.
235     std::shared_ptr<FenceTime> getCurrentFenceTime() const;
236 
237     // setConsumerUsageBits overrides the ConsumerBase method to OR
238     // DEFAULT_USAGE_FLAGS to usage.
239     status_t setConsumerUsageBits(uint64_t usage);
240 
241     // detachFromContext detaches the GLConsumer from the calling thread's
242     // current OpenGL ES context.  This context must be the same as the context
243     // that was current for previous calls to updateTexImage.
244     //
245     // Detaching a GLConsumer from an OpenGL ES context will result in the
246     // deletion of the OpenGL ES texture object into which the images were being
247     // streamed.  After a GLConsumer has been detached from the OpenGL ES
248     // context calls to updateTexImage will fail returning INVALID_OPERATION
249     // until the GLConsumer is attached to a new OpenGL ES context using the
250     // attachToContext method.
251     status_t detachFromContext();
252 
253     // attachToContext attaches a GLConsumer that is currently in the
254     // 'detached' state to the current OpenGL ES context.  A GLConsumer is
255     // in the 'detached' state iff detachFromContext has successfully been
256     // called and no calls to attachToContext have succeeded since the last
257     // detachFromContext call.  Calls to attachToContext made on a
258     // GLConsumer that is not in the 'detached' state will result in an
259     // INVALID_OPERATION error.
260     //
261     // The tex argument specifies the OpenGL ES texture object name in the
262     // new context into which the image contents will be streamed.  A successful
263     // call to attachToContext will result in this texture object being bound to
264     // the texture target and populated with the image contents that were
265     // current at the time of the last call to detachFromContext.
266     status_t attachToContext(uint32_t tex);
267 
268 protected:
269 
270     // abandonLocked overrides the ConsumerBase method to clear
271     // mCurrentTextureImage in addition to the ConsumerBase behavior.
272     virtual void abandonLocked();
273 
274     // dumpLocked overrides the ConsumerBase method to dump GLConsumer-
275     // specific info in addition to the ConsumerBase behavior.
276     virtual void dumpLocked(String8& result, const char* prefix) const;
277 
278     // acquireBufferLocked overrides the ConsumerBase method to update the
279     // mEglSlots array in addition to the ConsumerBase behavior.
280     virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
281             uint64_t maxFrameNumber = 0) override;
282 
283 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
284     virtual void onSlotCountChanged(int slotCount) override;
285 #endif
286     // releaseBufferLocked overrides the ConsumerBase method to update the
287     // mEglSlots array in addition to the ConsumerBase.
288 #if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
289     virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
290                                          EGLDisplay display = EGL_NO_DISPLAY,
291                                          EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
292 
releaseBufferLocked(int slot,const sp<GraphicBuffer> graphicBuffer,EGLSyncKHR eglFence)293     status_t releaseBufferLocked(int slot,
294             const sp<GraphicBuffer> graphicBuffer, EGLSyncKHR eglFence) {
295         return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
296     }
297 #endif
298 
299     struct PendingRelease {
PendingReleasePendingRelease300         PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
301 
302         bool isPending;
303         int currentTexture;
304         sp<GraphicBuffer> graphicBuffer;
305     };
306 
307     // This releases the buffer in the slot referenced by mCurrentTexture,
308     // then updates state to refer to the BufferItem, which must be a
309     // newly-acquired buffer. If pendingRelease is not null, the parameters
310     // which would have been passed to releaseBufferLocked upon the successful
311     // completion of the method will instead be returned to the caller, so that
312     // it may call releaseBufferLocked itself later.
313     status_t updateAndReleaseLocked(const BufferItem& item,
314             PendingRelease* pendingRelease = nullptr);
315 
316     // Binds mTexName and the current buffer to mTexTarget.  Uses
317     // mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
318     // bind succeeds, this calls doGLFenceWait.
319     status_t bindTextureImageLocked();
320 
321     // Gets the current EGLDisplay and EGLContext values, and compares them
322     // to mEglDisplay and mEglContext.  If the fields have been previously
323     // set, the values must match; if not, the fields are set to the current
324     // values.
325     // The contextCheck argument is used to ensure that a GL context is
326     // properly set; when set to false, the check is not performed.
327     status_t checkAndUpdateEglStateLocked(bool contextCheck = false);
328 
329 private:
330     // EglImage is a utility class for tracking and creating EGLImageKHRs. There
331     // is primarily just one image per slot, but there is also special cases:
332     //  - For releaseTexImage, we use a debug image (mReleasedTexImage)
333     //  - After freeBuffer, we must still keep the current image/buffer
334     // Reference counting EGLImages lets us handle all these cases easily while
335     // also only creating new EGLImages from buffers when required.
336     class EglImage : public LightRefBase<EglImage>  {
337     public:
338         explicit EglImage(sp<GraphicBuffer> graphicBuffer);
339 
340         // createIfNeeded creates an EGLImage if required (we haven't created
341         // one yet, or the EGLDisplay or crop-rect has changed).
342         status_t createIfNeeded(EGLDisplay display,
343                                 bool forceCreate = false);
344 
345         // This calls glEGLImageTargetTexture2DOES to bind the image to the
346         // texture in the specified texture target.
347         void bindToTextureTarget(uint32_t texTarget);
348 
graphicBuffer()349         const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
graphicBufferHandle()350         const native_handle* graphicBufferHandle() {
351             return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
352         }
353 
354     private:
355         // Only allow instantiation using ref counting.
356         friend class LightRefBase<EglImage>;
357         virtual ~EglImage();
358 
359         // createImage creates a new EGLImage from a GraphicBuffer.
360         EGLImageKHR createImage(EGLDisplay dpy,
361                 const sp<GraphicBuffer>& graphicBuffer);
362 
363         // Disallow copying
364         EglImage(const EglImage& rhs);
365         void operator = (const EglImage& rhs);
366 
367         // mGraphicBuffer is the buffer that was used to create this image.
368         sp<GraphicBuffer> mGraphicBuffer;
369 
370         // mEglImage is the EGLImage created from mGraphicBuffer.
371         EGLImageKHR mEglImage;
372 
373         // mEGLDisplay is the EGLDisplay that was used to create mEglImage.
374         EGLDisplay mEglDisplay;
375 
376         // mCropRect is the crop rectangle passed to EGL when mEglImage
377         // was created.
378         Rect mCropRect;
379     };
380 
381     // freeBufferLocked frees up the given buffer slot. If the slot has been
382     // initialized this will release the reference to the GraphicBuffer in that
383     // slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
384     //
385     // This method must be called with mMutex locked.
386     virtual void freeBufferLocked(int slotIndex);
387 
388     // computeCurrentTransformMatrixLocked computes the transform matrix for the
389     // current texture.  It uses mCurrentTransform and the current GraphicBuffer
390     // to compute this matrix and stores it in mCurrentTransformMatrix.
391     // mCurrentTextureImage must not be NULL.
392     void computeCurrentTransformMatrixLocked();
393 
394     // doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
395     // stream to ensure that it is safe for future OpenGL ES commands to
396     // access the current texture buffer.
397     status_t doGLFenceWaitLocked() const;
398 
399     // syncForReleaseLocked performs the synchronization needed to release the
400     // current slot from an OpenGL ES context.  If needed it will set the
401     // current slot's fence to guard against a producer accessing the buffer
402     // before the outstanding accesses have completed.
403     status_t syncForReleaseLocked(EGLDisplay dpy);
404 
405     // returns a graphic buffer used when the texture image has been released
406     static sp<GraphicBuffer> getDebugTexImageBuffer();
407 
408     // The default consumer usage flags that GLConsumer always sets on its
409     // BufferQueue instance; these will be OR:d with any additional flags passed
410     // from the GLConsumer user. In particular, GLConsumer will always
411     // consume buffers as hardware textures.
412     static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
413 
414     // mCurrentTextureImage is the EglImage/buffer of the current texture. It's
415     // possible that this buffer is not associated with any buffer slot, so we
416     // must track it separately in order to support the getCurrentBuffer method.
417     sp<EglImage> mCurrentTextureImage;
418 
419     // mCurrentCrop is the crop rectangle that applies to the current texture.
420     // It gets set each time updateTexImage is called.
421     Rect mCurrentCrop;
422 
423     // mCurrentTransform is the transform identifier for the current texture. It
424     // gets set each time updateTexImage is called.
425     uint32_t mCurrentTransform;
426 
427     // mCurrentScalingMode is the scaling mode for the current texture. It gets
428     // set each time updateTexImage is called.
429     uint32_t mCurrentScalingMode;
430 
431     // mCurrentFence is the fence received from BufferQueue in updateTexImage.
432     sp<Fence> mCurrentFence;
433 
434     // The FenceTime wrapper around mCurrentFence.
435     std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};
436 
437     // mCurrentTransformMatrix is the transform matrix for the current texture.
438     // It gets computed by computeTransformMatrix each time updateTexImage is
439     // called.
440     float mCurrentTransformMatrix[16];
441 
442     // mCurrentTimestamp is the timestamp for the current texture. It
443     // gets set each time updateTexImage is called.
444     int64_t mCurrentTimestamp;
445 
446     // mCurrentDataSpace is the dataspace for the current texture. It
447     // gets set each time updateTexImage is called.
448     android_dataspace mCurrentDataSpace;
449 
450     // mCurrentFrameNumber is the frame counter for the current texture.
451     // It gets set each time updateTexImage is called.
452     uint64_t mCurrentFrameNumber;
453 
454     uint32_t mDefaultWidth, mDefaultHeight;
455 
456     // mFilteringEnabled indicates whether the transform matrix is computed for
457     // use with bilinear filtering. It defaults to true and is changed by
458     // setFilteringEnabled().
459     bool mFilteringEnabled;
460 
461     // mTexName is the name of the OpenGL texture to which streamed images will
462     // be bound when updateTexImage is called. It is set at construction time
463     // and can be changed with a call to attachToContext.
464     uint32_t mTexName;
465 
466     // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
467     // extension should be used to prevent buffers from being dequeued before
468     // it's safe for them to be written. It gets set at construction time and
469     // never changes.
470     const bool mUseFenceSync;
471 
472     // mTexTarget is the GL texture target with which the GL texture object is
473     // associated.  It is set in the constructor and never changed.  It is
474     // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
475     // Browser.  In that case it is set to GL_TEXTURE_2D to allow
476     // glCopyTexSubImage to read from the texture.  This is a hack to work
477     // around a GL driver limitation on the number of FBO attachments, which the
478     // browser's tile cache exceeds.
479     const uint32_t mTexTarget;
480 
481     // EGLSlot contains the information and object references that
482     // GLConsumer maintains about a BufferQueue buffer slot.
483     struct EglSlot {
484 #if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
EglSlotEglSlot485         EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
486 #endif
487         // mEglImage is the EGLImage created from mGraphicBuffer.
488         sp<EglImage> mEglImage;
489 #if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
490         // mFence is the EGL sync object that must signal before the buffer
491         // associated with this buffer slot may be dequeued. It is initialized
492         // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
493         // on a compile-time option) set to a new sync object in updateTexImage.
494         EGLSyncKHR mEglFence;
495 #endif
496     };
497 
498     // mEglDisplay is the EGLDisplay with which this GLConsumer is currently
499     // associated.  It is intialized to EGL_NO_DISPLAY and gets set to the
500     // current display when updateTexImage is called for the first time and when
501     // attachToContext is called.
502     EGLDisplay mEglDisplay;
503 
504     // mEglContext is the OpenGL ES context with which this GLConsumer is
505     // currently associated.  It is initialized to EGL_NO_CONTEXT and gets set
506     // to the current GL context when updateTexImage is called for the first
507     // time and when attachToContext is called.
508     EGLContext mEglContext;
509 
510     // mEGLSlots stores the buffers that have been allocated by the BufferQueue
511     // for each buffer slot.  It is initialized to null pointers, and gets
512     // filled in with the result of BufferQueue::acquire when the
513     // client dequeues a buffer from a
514     // slot that has not yet been used. The buffer allocated to a slot will also
515     // be replaced if the requested buffer usage or geometry differs from that
516     // of the buffer allocated to a slot.
517 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
518     std::vector<EglSlot> mEglSlots;
519 #else
520     EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
521 #endif
522     // mCurrentTexture is the buffer slot index of the buffer that is currently
523     // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
524     // indicating that no buffer slot is currently bound to the texture. Note,
525     // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
526     // that no buffer is bound to the texture. A call to setBufferCount will
527     // reset mCurrentTexture to INVALID_BUFFER_SLOT.
528     int mCurrentTexture;
529 
530     // mAttached indicates whether the ConsumerBase is currently attached to
531     // an OpenGL ES context.  For legacy reasons, this is initialized to true,
532     // indicating that the ConsumerBase is considered to be attached to
533     // whatever context is current at the time of the first updateTexImage call.
534     // It is set to false by detachFromContext, and then set to true again by
535     // attachToContext.
536     bool mAttached;
537 
538     // protects static initialization
539     static Mutex sStaticInitLock;
540 
541     // mReleasedTexImageBuffer is a buffer placeholder used when in single buffer
542     // mode and releaseTexImage() has been called
543     static sp<GraphicBuffer> sReleasedTexImageBuffer;
544     sp<EglImage> mReleasedTexImage;
545 };
546 
547 // ----------------------------------------------------------------------------
548 }; // namespace android
549 
550 #endif // ANDROID_GUI_CONSUMER_H
551