Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2010, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "DoubleBufferedTexture.h"
     28 
     29 #include "ClassTracker.h"
     30 #include "GLUtils.h"
     31 
     32 #define LOG_NDEBUG 1
     33 #define LOG_TAG "DoubleBufferedTexture.cpp"
     34 #include <utils/Log.h>
     35 
     36 namespace WebCore {
     37 
     38 DoubleBufferedTexture::DoubleBufferedTexture(EGLContext sharedContext, SharedTextureMode mode)
     39 {
     40     m_sharedTextureMode = mode;
     41 
     42     m_textureA = new SharedTexture(m_sharedTextureMode);
     43     if (m_sharedTextureMode == EglImageMode)
     44         m_textureB = new SharedTexture(m_sharedTextureMode);
     45     else
     46         m_textureB = 0;
     47 
     48     m_display = eglGetCurrentDisplay();
     49     m_pContext = EGL_NO_CONTEXT;
     50     m_cContext = sharedContext;
     51     m_writeableTexture = m_textureA;
     52     m_lockedConsumerTexture = GL_NO_TEXTURE;
     53     m_supportsEGLImage = GLUtils::isEGLImageSupported();
     54 #ifdef DEBUG_COUNT
     55     ClassTracker::instance()->increment("DoubleBufferedTexture");
     56 #endif
     57 }
     58 
     59 DoubleBufferedTexture::~DoubleBufferedTexture()
     60 {
     61 #ifdef DEBUG_COUNT
     62     ClassTracker::instance()->decrement("DoubleBufferedTexture");
     63 #endif
     64     delete m_textureA;
     65     delete m_textureB;
     66 }
     67 
     68 SharedTexture* DoubleBufferedTexture::getWriteableTexture()
     69 {
     70     if (m_sharedTextureMode == SurfaceTextureMode)
     71         return m_textureA;
     72     return reinterpret_cast<SharedTexture*>(
     73         android_atomic_release_load((int32_t*)&m_writeableTexture));
     74 }
     75 
     76 SharedTexture* DoubleBufferedTexture::getReadableTexture()
     77 {
     78     if (m_sharedTextureMode == SurfaceTextureMode)
     79         return m_textureA;
     80     return (getWriteableTexture() != m_textureA) ? m_textureA : m_textureB;
     81 }
     82 
     83 EGLContext DoubleBufferedTexture::producerAcquireContext()
     84 {
     85     if (m_sharedTextureMode == SurfaceTextureMode)
     86         return EGL_NO_CONTEXT;
     87 
     88     if (m_pContext != EGL_NO_CONTEXT) {
     89         LOGV("AquireContext has previously generated a context.\n");
     90         return m_pContext;
     91     }
     92 
     93     // check to see if a context already exists on this thread
     94     EGLContext context = eglGetCurrentContext();
     95 
     96     // if no context exists then create one
     97     if (context == EGL_NO_CONTEXT) {
     98         EGLContext sharedContext = m_supportsEGLImage ? EGL_NO_CONTEXT : m_cContext;
     99         context = GLUtils::createBackgroundContext(sharedContext);
    100     }
    101 
    102     if (context == EGL_NO_CONTEXT) {
    103         LOGE("eglCreateContext failed");
    104         return EGL_NO_CONTEXT;
    105     }
    106 
    107     // initialize the producer's textures
    108     m_textureA->lock();
    109     if (m_sharedTextureMode == EglImageMode)
    110         m_textureB->lock();
    111 
    112     m_textureA->initSourceTexture();
    113     LOGV("Initialized Textures A (%d)", m_textureA->getSourceTextureId());
    114     if (m_sharedTextureMode == EglImageMode) {
    115         m_textureB->initSourceTexture();
    116         LOGV("Initialized Textures B (%d)", m_textureB->getSourceTextureId());
    117     }
    118 
    119     m_textureA->unlock();
    120     if (m_sharedTextureMode == EglImageMode)
    121         m_textureB->unlock();
    122 
    123     m_pContext = context;
    124     return context;
    125 }
    126 
    127 // For MediaTexture only
    128 void DoubleBufferedTexture::producerDeleteTextures()
    129 {
    130     m_textureA->lock();
    131     if (m_sharedTextureMode == EglImageMode)
    132         m_textureB->lock();
    133 
    134     LOGV("Deleting Producer Textures A (%d)", m_textureA->getSourceTextureId());
    135     m_textureA->deleteSourceTexture();
    136     if (m_sharedTextureMode == EglImageMode){
    137         LOGV("Deleting Producer Textures B (%d)", m_textureB->getSourceTextureId());
    138         m_textureB->deleteSourceTexture();
    139     }
    140 
    141     m_textureA->unlock();
    142     if (m_sharedTextureMode == EglImageMode)
    143         m_textureB->unlock();
    144 }
    145 
    146 // For MediaTexture only
    147 void DoubleBufferedTexture::consumerDeleteTextures()
    148 {
    149     m_textureA->lock();
    150     if (m_sharedTextureMode == EglImageMode)
    151         m_textureB->lock();
    152 
    153     LOGV("Deleting Consumer Textures A (%d)", m_textureA->getTargetTextureId());
    154     m_textureA->deleteTargetTexture();
    155     if (m_sharedTextureMode == EglImageMode) {
    156         LOGV("Deleting Consumer Textures B (%d)", m_textureB->getTargetTextureId());
    157         m_textureB->deleteTargetTexture();
    158     }
    159 
    160     m_textureA->unlock();
    161     if (m_sharedTextureMode == EglImageMode)
    162         m_textureB->unlock();
    163 }
    164 
    165 TextureInfo* DoubleBufferedTexture::producerLock()
    166 {
    167     SharedTexture* sharedTex = getWriteableTexture();
    168     LOGV("Acquiring P Lock (%d)", sharedTex->getSourceTextureId());
    169     TextureInfo* texInfo = sharedTex->lockSource();
    170     LOGV("Acquired P Lock");
    171 
    172     return texInfo;
    173 }
    174 
    175 void DoubleBufferedTexture::producerRelease()
    176 {
    177     // get the writable texture and unlock it
    178     SharedTexture* sharedTex = getWriteableTexture();
    179     LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId());
    180     sharedTex->releaseSource();
    181     LOGV("Released P Lock (%d)", sharedTex->getSourceTextureId());
    182 }
    183 
    184 void DoubleBufferedTexture::producerReleaseAndSwap()
    185 {
    186     producerRelease();
    187     if (m_sharedTextureMode == EglImageMode) {
    188         // swap the front and back buffers using an atomic op for the memory barrier
    189         android_atomic_acquire_store((int32_t)getReadableTexture(), (int32_t*)&m_writeableTexture);
    190     }
    191 }
    192 
    193 TextureInfo* DoubleBufferedTexture::consumerLock()
    194 {
    195     SharedTexture* sharedTex = getReadableTexture();
    196     LOGV("Acquiring C Lock (%d)", sharedTex->getSourceTextureId());
    197     m_lockedConsumerTexture = sharedTex;
    198 
    199     TextureInfo* texInfo = sharedTex->lockTarget();
    200     LOGV("Acquired C Lock");
    201 
    202     if (!texInfo)
    203         LOGV("Released C Lock (Empty)");
    204 
    205     return texInfo;
    206 }
    207 
    208 void DoubleBufferedTexture::consumerRelease()
    209 {
    210     // we must check to see what texture the consumer had locked since the
    211     // producer may have swapped out the readable buffer
    212     SharedTexture* sharedTex = m_lockedConsumerTexture;
    213     sharedTex->releaseTarget();
    214     LOGV("Released C Lock (%d)", sharedTex->getSourceTextureId());
    215 }
    216 
    217 } // namespace WebCore
    218