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