• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DoubleBufferedTexture(EGLContext sharedContext,SharedTextureMode mode)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 
~DoubleBufferedTexture()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 
getWriteableTexture()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 
getReadableTexture()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 
producerAcquireContext()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
producerDeleteTextures()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
consumerDeleteTextures()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 
producerLock()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 
producerRelease()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 
producerReleaseAndSwap()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 
consumerLock()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 
consumerRelease()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