Home | History | Annotate | Download | only in surfacetexture
      1 /*
      2  * Copyright (C) 2018 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 #pragma once
     18 
     19 #include <EGL/egl.h>
     20 #include <EGL/eglext.h>
     21 
     22 #include <gui/BufferQueueDefs.h>
     23 
     24 #include <ui/FenceTime.h>
     25 #include <ui/GraphicBuffer.h>
     26 #include <utils/Mutex.h>
     27 
     28 namespace android {
     29 
     30 class SurfaceTexture;
     31 
     32 /*
     33  * EGLConsumer implements the parts of SurfaceTexture that deal with
     34  * textures attached to an GL context.
     35  */
     36 class EGLConsumer {
     37 public:
     38     EGLConsumer();
     39 
     40     /**
     41      * updateTexImage acquires the most recently queued buffer, and sets the
     42      * image contents of the target texture to it.
     43      *
     44      * This call may only be made while the OpenGL ES context to which the
     45      * target texture belongs is bound to the calling thread.
     46      *
     47      * This calls doGLFenceWait to ensure proper synchronization.
     48      */
     49     status_t updateTexImage(SurfaceTexture& st);
     50 
     51     /*
     52      * releaseTexImage releases the texture acquired in updateTexImage().
     53      * This is intended to be used in single buffer mode.
     54      *
     55      * This call may only be made while the OpenGL ES context to which the
     56      * target texture belongs is bound to the calling thread.
     57      */
     58     status_t releaseTexImage(SurfaceTexture& st);
     59 
     60     /**
     61      * detachFromContext detaches the EGLConsumer from the calling thread's
     62      * current OpenGL ES context.  This context must be the same as the context
     63      * that was current for previous calls to updateTexImage.
     64      *
     65      * Detaching a EGLConsumer from an OpenGL ES context will result in the
     66      * deletion of the OpenGL ES texture object into which the images were being
     67      * streamed.  After a EGLConsumer has been detached from the OpenGL ES
     68      * context calls to updateTexImage will fail returning INVALID_OPERATION
     69      * until the EGLConsumer is attached to a new OpenGL ES context using the
     70      * attachToContext method.
     71      */
     72     status_t detachFromContext(SurfaceTexture& st);
     73 
     74     /**
     75      * attachToContext attaches a EGLConsumer that is currently in the
     76      * 'detached' state to the current OpenGL ES context.  A EGLConsumer is
     77      * in the 'detached' state iff detachFromContext has successfully been
     78      * called and no calls to attachToContext have succeeded since the last
     79      * detachFromContext call.  Calls to attachToContext made on a
     80      * EGLConsumer that is not in the 'detached' state will result in an
     81      * INVALID_OPERATION error.
     82      *
     83      * The tex argument specifies the OpenGL ES texture object name in the
     84      * new context into which the image contents will be streamed.  A successful
     85      * call to attachToContext will result in this texture object being bound to
     86      * the texture target and populated with the image contents that were
     87      * current at the time of the last call to detachFromContext.
     88      */
     89     status_t attachToContext(uint32_t tex, SurfaceTexture& st);
     90 
     91     /**
     92      * onAcquireBufferLocked amends the ConsumerBase method to update the
     93      * mEglSlots array in addition to the ConsumerBase behavior.
     94      */
     95     void onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st);
     96 
     97     /**
     98      * onReleaseBufferLocked amends the ConsumerBase method to update the
     99      * mEglSlots array in addition to the ConsumerBase.
    100      */
    101     void onReleaseBufferLocked(int slot);
    102 
    103     /**
    104      * onFreeBufferLocked frees up the given buffer slot. If the slot has been
    105      * initialized this will release the reference to the GraphicBuffer in that
    106      * slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
    107      */
    108     void onFreeBufferLocked(int slotIndex);
    109 
    110     /**
    111      * onAbandonLocked amends the ConsumerBase method to clear
    112      * mCurrentTextureImage in addition to the ConsumerBase behavior.
    113      */
    114     void onAbandonLocked();
    115 
    116 protected:
    117     struct PendingRelease {
    118         PendingRelease()
    119                 : isPending(false)
    120                 , currentTexture(-1)
    121                 , graphicBuffer()
    122                 , display(nullptr)
    123                 , fence(nullptr) {}
    124 
    125         bool isPending;
    126         int currentTexture;
    127         sp<GraphicBuffer> graphicBuffer;
    128         EGLDisplay display;
    129         EGLSyncKHR fence;
    130     };
    131 
    132     /**
    133      * This releases the buffer in the slot referenced by mCurrentTexture,
    134      * then updates state to refer to the BufferItem, which must be a
    135      * newly-acquired buffer. If pendingRelease is not null, the parameters
    136      * which would have been passed to releaseBufferLocked upon the successful
    137      * completion of the method will instead be returned to the caller, so that
    138      * it may call releaseBufferLocked itself later.
    139      */
    140     status_t updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
    141                                     SurfaceTexture& st);
    142 
    143     /**
    144      * Binds mTexName and the current buffer to mTexTarget.  Uses
    145      * mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
    146      * bind succeeds, this calls doGLFenceWait.
    147      */
    148     status_t bindTextureImageLocked(SurfaceTexture& st);
    149 
    150     /**
    151      * Gets the current EGLDisplay and EGLContext values, and compares them
    152      * to mEglDisplay and mEglContext.  If the fields have been previously
    153      * set, the values must match; if not, the fields are set to the current
    154      * values.
    155      * The contextCheck argument is used to ensure that a GL context is
    156      * properly set; when set to false, the check is not performed.
    157      */
    158     status_t checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck = false);
    159 
    160     /**
    161      * EglImage is a utility class for tracking and creating EGLImageKHRs. There
    162      * is primarily just one image per slot, but there is also special cases:
    163      *  - For releaseTexImage, we use a debug image (mReleasedTexImage)
    164      *  - After freeBuffer, we must still keep the current image/buffer
    165      * Reference counting EGLImages lets us handle all these cases easily while
    166      * also only creating new EGLImages from buffers when required.
    167      */
    168     class EglImage : public LightRefBase<EglImage> {
    169     public:
    170         EglImage(sp<GraphicBuffer> graphicBuffer);
    171 
    172         /**
    173          * createIfNeeded creates an EGLImage if required (we haven't created
    174          * one yet, or the EGLDisplay or crop-rect has changed).
    175          */
    176         status_t createIfNeeded(EGLDisplay display, bool forceCreate = false);
    177 
    178         /**
    179          * This calls glEGLImageTargetTexture2DOES to bind the image to the
    180          * texture in the specified texture target.
    181          */
    182         void bindToTextureTarget(uint32_t texTarget);
    183 
    184         const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
    185         const native_handle* graphicBufferHandle() {
    186             return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
    187         }
    188 
    189     private:
    190         // Only allow instantiation using ref counting.
    191         friend class LightRefBase<EglImage>;
    192         virtual ~EglImage();
    193 
    194         // createImage creates a new EGLImage from a GraphicBuffer.
    195         EGLImageKHR createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer);
    196 
    197         // Disallow copying
    198         EglImage(const EglImage& rhs);
    199         void operator=(const EglImage& rhs);
    200 
    201         // mGraphicBuffer is the buffer that was used to create this image.
    202         sp<GraphicBuffer> mGraphicBuffer;
    203 
    204         // mEglImage is the EGLImage created from mGraphicBuffer.
    205         EGLImageKHR mEglImage;
    206 
    207         // mEGLDisplay is the EGLDisplay that was used to create mEglImage.
    208         EGLDisplay mEglDisplay;
    209 
    210         // mCropRect is the crop rectangle passed to EGL when mEglImage
    211         // was created.
    212         Rect mCropRect;
    213     };
    214 
    215     /**
    216      * doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
    217      * stream to ensure that it is safe for future OpenGL ES commands to
    218      * access the current texture buffer.
    219      */
    220     status_t doGLFenceWaitLocked(SurfaceTexture& st) const;
    221 
    222     /**
    223      * syncForReleaseLocked performs the synchronization needed to release the
    224      * current slot from an OpenGL ES context.  If needed it will set the
    225      * current slot's fence to guard against a producer accessing the buffer
    226      * before the outstanding accesses have completed.
    227      */
    228     status_t syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st);
    229 
    230     /**
    231      * returns a graphic buffer used when the texture image has been released
    232      */
    233     static sp<GraphicBuffer> getDebugTexImageBuffer();
    234 
    235     /**
    236      * The default consumer usage flags that EGLConsumer always sets on its
    237      * BufferQueue instance; these will be OR:d with any additional flags passed
    238      * from the EGLConsumer user. In particular, EGLConsumer will always
    239      * consume buffers as hardware textures.
    240      */
    241     static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
    242 
    243     /**
    244      * mCurrentTextureImage is the EglImage/buffer of the current texture. It's
    245      * possible that this buffer is not associated with any buffer slot, so we
    246      * must track it separately in order to support the getCurrentBuffer method.
    247      */
    248     sp<EglImage> mCurrentTextureImage;
    249 
    250     /**
    251      * EGLSlot contains the information and object references that
    252      * EGLConsumer maintains about a BufferQueue buffer slot.
    253      */
    254     struct EglSlot {
    255         EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
    256 
    257         /**
    258          * mEglImage is the EGLImage created from mGraphicBuffer.
    259          */
    260         sp<EglImage> mEglImage;
    261 
    262         /**
    263          * mFence is the EGL sync object that must signal before the buffer
    264          * associated with this buffer slot may be dequeued. It is initialized
    265          * to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
    266          * on a compile-time option) set to a new sync object in updateTexImage.
    267          */
    268         EGLSyncKHR mEglFence;
    269     };
    270 
    271     /**
    272      * mEglDisplay is the EGLDisplay with which this EGLConsumer is currently
    273      * associated.  It is intialized to EGL_NO_DISPLAY and gets set to the
    274      * current display when updateTexImage is called for the first time and when
    275      * attachToContext is called.
    276      */
    277     EGLDisplay mEglDisplay;
    278 
    279     /**
    280      * mEglContext is the OpenGL ES context with which this EGLConsumer is
    281      * currently associated.  It is initialized to EGL_NO_CONTEXT and gets set
    282      * to the current GL context when updateTexImage is called for the first
    283      * time and when attachToContext is called.
    284      */
    285     EGLContext mEglContext;
    286 
    287     /**
    288      * mEGLSlots stores the buffers that have been allocated by the BufferQueue
    289      * for each buffer slot.  It is initialized to null pointers, and gets
    290      * filled in with the result of BufferQueue::acquire when the
    291      * client dequeues a buffer from a
    292      * slot that has not yet been used. The buffer allocated to a slot will also
    293      * be replaced if the requested buffer usage or geometry differs from that
    294      * of the buffer allocated to a slot.
    295      */
    296     EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
    297 
    298     /**
    299      * protects static initialization
    300      */
    301     static Mutex sStaticInitLock;
    302 
    303     /**
    304      * mReleasedTexImageBuffer is a dummy buffer used when in single buffer
    305      * mode and releaseTexImage() has been called
    306      */
    307     static sp<GraphicBuffer> sReleasedTexImageBuffer;
    308     sp<EglImage> mReleasedTexImage;
    309 };
    310 
    311 }  // namespace android
    312