diff options
-rw-r--r-- | WebCore/platform/graphics/android/DoubleBufferedTexture.cpp | 150 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/DoubleBufferedTexture.h | 75 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/GLUtils.cpp | 29 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/GLUtils.h | 8 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/SharedTexture.cpp | 185 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/SharedTexture.h | 134 |
6 files changed, 570 insertions, 11 deletions
diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp new file mode 100644 index 0000000..e713398 --- /dev/null +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp @@ -0,0 +1,150 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DoubleBufferedTexture.h" +#include "GLUtils.h" + +#define LOG_NDEBUG 1 +#define LOG_TAG "DoubleBufferedTexture.cpp" +#include <utils/Log.h> + +namespace WebCore { + +DoubleBufferedTexture::DoubleBufferedTexture(EGLContext sharedContext) { + + // the mutex ensures that the variables are not used in any other thread + // until the constructor has the opportunity to initialize them + android::Mutex::Autolock lock(m_varLock); + m_display = eglGetCurrentDisplay(); + m_pContext = EGL_NO_CONTEXT; + m_cContext = sharedContext; + m_frontTexture = GL_NO_TEXTURE; + m_lockedConsumerTexture = GL_NO_TEXTURE; + m_supportsEGLImage = GLUtils::isEGLImageSupported(); +} + +SharedTexture* DoubleBufferedTexture::getFrontTexture() { + return (m_frontTexture == &m_textureA) ? &m_textureA : &m_textureB; +} + +SharedTexture* DoubleBufferedTexture::getBackTexture() { + return (m_frontTexture != &m_textureA) ? &m_textureA : &m_textureB; +} + +EGLContext DoubleBufferedTexture::producerAcquireContext() { + // ensure that the constructor has completed and all values are initialized + android::Mutex::Autolock lock(m_varLock); + + if (m_pContext != EGL_NO_CONTEXT) { + LOGV("AquireContext has previously generated a context.\n"); + return m_pContext; + } + + // check to see if a context already exists on this thread + EGLContext context = eglGetCurrentContext(); + + // if no context exists then create one + if (context == EGL_NO_CONTEXT) { + EGLContext sharedContext = m_supportsEGLImage ? EGL_NO_CONTEXT : m_cContext; + context = GLUtils::createBackgroundContext(sharedContext); + } + + if (context == EGL_NO_CONTEXT) { + LOGE("eglCreateContext failed"); + return EGL_NO_CONTEXT; + } + + // initialize the producer's textures + m_textureA.lock(); + m_textureB.lock(); + m_textureA.initSourceTexture(); + m_textureB.initSourceTexture(); + LOGV("Initialized Textures A/B (%d:%d)", m_textureA.getSourceTextureId(), + m_textureB.getSourceTextureId()); + m_textureA.unlock(); + m_textureB.unlock(); + + // select a front buffer + m_frontTexture = &m_textureA; + + m_pContext = context; + return context; +} + +TextureInfo* DoubleBufferedTexture::producerLock() { + m_varLock.lock(); + SharedTexture* sharedTex = getFrontTexture(); + m_varLock.unlock(); + LOGV("Acquiring P Lock (%d)", sharedTex->getSourceTextureId()); + TextureInfo* texInfo = sharedTex->lockSource(); + LOGV("Acquired P Lock"); + + return texInfo; +} + +void DoubleBufferedTexture::producerRelease() { + m_varLock.lock(); + // get the front texture and cache the id + SharedTexture* sharedTex = getFrontTexture(); + LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId()); + m_varLock.unlock(); + + sharedTex->releaseSource(); + + // swap the front and back buffers + m_varLock.lock(); + m_frontTexture = (sharedTex == &m_textureA) ? &m_textureB : &m_textureA; + LOGV("Released P Lock (%d)", sharedTex->getSourceTextureId()); + m_varLock.unlock(); +} + +TextureInfo* DoubleBufferedTexture::consumerLock() { + m_varLock.lock(); + SharedTexture* sharedTex = getBackTexture(); + LOGV("Acquiring C Lock (%d)", sharedTex->getSourceTextureId()); + m_lockedConsumerTexture = sharedTex; + m_varLock.unlock(); + + TextureInfo* texInfo = sharedTex->lockTarget(); + LOGV("Acquired C Lock"); + + if (!texInfo) { + LOGV("Released C Lock (Empty)"); + } + + return texInfo; +} + +void DoubleBufferedTexture::consumerRelease() { + android::Mutex::Autolock lock(m_varLock); + // we must check to see what texture the consumer had locked since the + // producer may have swapped out the front buffer + SharedTexture* sharedTex = m_lockedConsumerTexture; + sharedTex->releaseTarget(); + LOGV("Released C Lock (%d)", sharedTex->getSourceTextureId()); +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/WebCore/platform/graphics/android/DoubleBufferedTexture.h new file mode 100644 index 0000000..1c629a7 --- /dev/null +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.h @@ -0,0 +1,75 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DoubleBufferedTexture__DEFINED +#define DoubleBufferedTexture__DEFINED + +#include <utils/threads.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include "SharedTexture.h" + +namespace WebCore { + +class DoubleBufferedTexture { +public: + // consumer thread functions + DoubleBufferedTexture(EGLContext sharedContext); + + // provider thread functions + TextureInfo* producerLock(); + void producerRelease(); + EGLContext producerAcquireContext(); + + // consumer thread functions + TextureInfo* consumerLock(); + void consumerRelease(); + +private: + SharedTexture* getFrontTexture(); + SharedTexture* getBackTexture(); + + EGLDisplay m_display; + + EGLContext m_pContext; + EGLContext m_cContext; + + SharedTexture m_textureA; + SharedTexture m_textureB; + SharedTexture* m_frontTexture; + SharedTexture* m_lockedConsumerTexture; // only used by the consumer + + android::Mutex m_varLock; + + bool m_supportsEGLImage; +}; + + +} // namespace WebCore + +#endif // DoubleBufferedTexture__DEFINED diff --git a/WebCore/platform/graphics/android/GLUtils.cpp b/WebCore/platform/graphics/android/GLUtils.cpp index 7e93d1b..e9c0796 100644 --- a/WebCore/platform/graphics/android/GLUtils.cpp +++ b/WebCore/platform/graphics/android/GLUtils.cpp @@ -114,6 +114,24 @@ bool GLUtils::checkGlErrorOn(void* p, const char* op) { } ///////////////////////////////////////////////////////////////////////////////////////// +// GL & EGL extension checks +///////////////////////////////////////////////////////////////////////////////////////// + +bool GLUtils::isEGLImageSupported() { + const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); + const char* glExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + + return strstr(eglExtensions, "EGL_KHR_image_base") && + strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") && + strstr(glExtensions, "GL_OES_EGL_image"); +} + +bool GLUtils::isEGLFenceSyncSupported() { + const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS); + return strstr(eglExtensions, "EGL_KHR_fence_sync"); +} + +///////////////////////////////////////////////////////////////////////////////////////// // Textures utilities ///////////////////////////////////////////////////////////////////////////////////////// @@ -257,10 +275,7 @@ GLuint GLUtils::createSampleTexture() { return texture; } -GLuint GLUtils::createTextureWithBitmap(SkBitmap& bitmap, GLint filter) { - GLuint texture; - glGenTextures(1, &texture); - GLUtils::checkGlError("glGenTextures"); +void GLUtils::createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, texture); GLUtils::checkGlError("glBindTexture"); @@ -274,7 +289,6 @@ GLuint GLUtils::createTextureWithBitmap(SkBitmap& bitmap, GLint filter) { GLUtils::checkGlError("glTexImage2D"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - return texture; } void GLUtils::updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter) { @@ -301,15 +315,12 @@ void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) { GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR)); } -GLuint GLUtils::createTextureFromEGLImage(EGLImageKHR image, GLint filter) { - GLuint texture; - glGenTextures(1, &texture); +void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter) { glBindTexture(GL_TEXTURE_2D, texture); GLUtils::checkGlError("glBindTexture"); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - return texture; } } // namespace WebCore diff --git a/WebCore/platform/graphics/android/GLUtils.h b/WebCore/platform/graphics/android/GLUtils.h index eb2cbdf..1886c04 100644 --- a/WebCore/platform/graphics/android/GLUtils.h +++ b/WebCore/platform/graphics/android/GLUtils.h @@ -50,14 +50,18 @@ public: static bool checkGlErrorOn(void* p, const char* op); static bool checkGlError(const char* op); + // GL & EGL extension checks + static bool isEGLImageSupported(); + static bool isEGLFenceSyncSupported(); + // Texture utilities static EGLContext createBackgroundContext(EGLContext sharedContext); static void deleteTexture(GLuint* texture); static GLuint createSampleTexture(); - static GLuint createTextureWithBitmap(SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); static void updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); - static GLuint createTextureFromEGLImage(EGLImageKHR image, GLint filter = GL_LINEAR); + static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); }; } // namespace WebCore diff --git a/WebCore/platform/graphics/android/SharedTexture.cpp b/WebCore/platform/graphics/android/SharedTexture.cpp new file mode 100644 index 0000000..fee9c32 --- /dev/null +++ b/WebCore/platform/graphics/android/SharedTexture.cpp @@ -0,0 +1,185 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SharedTexture.h" +#include "GLUtils.h" + +#define LOG_NDEBUG 1 +#define LOG_TAG "SharedTexture.cpp" +#include <utils/Log.h> + +namespace WebCore { + +TextureInfo::TextureInfo() { + m_textureId = GL_NO_TEXTURE; + m_width = 0; + m_height = 0; + m_internalFormat = 0; +} + +bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) { + return otherTexture->m_width == m_width && + otherTexture->m_height == m_height && + otherTexture->m_internalFormat == m_internalFormat; +} + +void TextureInfo::copyAttributes(const TextureInfo* sourceTexture) { + m_width = sourceTexture->m_width; + m_height = sourceTexture->m_height; + m_internalFormat = sourceTexture->m_internalFormat; +} + +bool TextureInfo::operator==(const TextureInfo& otherTexture) { + return otherTexture.m_textureId == m_textureId && equalsAttributes(&otherTexture); +} + +SharedTexture::SharedTexture() { + + // the mutex ensures that the variables are not used in any other thread + // until the constructor has the opportunity to initialize them + android::Mutex::Autolock lock(m_lock); + m_display = eglGetCurrentDisplay(); + m_eglImage = EGL_NO_IMAGE_KHR; + m_isNewImage = true; + m_syncObject = EGL_NO_SYNC_KHR; + m_supportsEGLImage = GLUtils::isEGLImageSupported(); + m_supportsEGLFenceSyncKHR = GLUtils::isEGLFenceSyncSupported(); + + //TODO temporarily disable fence sync until nvidia implementation is complete + m_supportsEGLFenceSyncKHR = false; + + LOGI("imageEGL: %d syncKHR: %d", m_supportsEGLImage, m_supportsEGLFenceSyncKHR); +} + +// called by the consumer when it no longer wants to consume and after it has +// terminated all providers. It is up to the providers to terminate their +// textures in the case that EGLImages are used +SharedTexture::~SharedTexture() { + if (m_supportsEGLImage) { + eglDestroyImageKHR(m_display, m_eglImage); + glDeleteTextures(1, &m_targetTexture.m_textureId); + } else { + glDeleteTextures(1, &m_sourceTexture.m_textureId); + } + m_lock.unlock(); +} + +void SharedTexture::initSourceTexture() { + glGenTextures(1, &m_sourceTexture.m_textureId); +} + +TextureInfo* SharedTexture::lockSource() { + m_lock.lock(); + + if (m_supportsEGLFenceSyncKHR && m_syncObject != EGL_NO_SYNC_KHR) { + + EGLint status = eglClientWaitSyncKHR(m_display, m_syncObject, 0, 1000000); + + if (status == EGL_TIMEOUT_EXPIRED_KHR) { + LOGE("Sync timeout for shared texture (%d)", m_sourceTexture.m_textureId); + } + + eglDestroySyncKHR(m_display, m_syncObject); + m_syncObject = EGL_NO_SYNC_KHR; + } + + return &m_sourceTexture; +} + +void SharedTexture::releaseSource() { + + if (m_supportsEGLImage) { + // delete the existing image if needed + if (!m_sourceTexture.equalsAttributes(&m_targetTexture)) { + if (m_eglImage != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(m_display, m_eglImage); + m_eglImage = EGL_NO_IMAGE_KHR; + m_isNewImage = true; + } + m_targetTexture.copyAttributes(&m_sourceTexture); + } + + // create an image from the texture + if (m_eglImage == EGL_NO_IMAGE_KHR) { + GLUtils::createEGLImageFromTexture(m_sourceTexture.m_textureId, &m_eglImage); + LOGV("Generating Image (%d) 0x%x", m_sourceTexture.m_textureId, m_eglImage); + } + + glFinish(); // ensures the texture is ready to be used by the consumer + + } else { + + m_targetTexture = m_sourceTexture; + + // in the case of shared contexts we must flush the texture edits to the + // GPU. This ensures the edits complete prior to allowing the texture to + // be bound on the producers context. + glFlush(); + } + + m_lock.unlock(); +} + +TextureInfo* SharedTexture::lockTarget() { + m_lock.lock(); + + if ((!m_supportsEGLImage && m_targetTexture.m_textureId == GL_NO_TEXTURE) || + (m_supportsEGLImage && m_eglImage == EGL_NO_IMAGE_KHR)) { + m_lock.unlock(); + return 0; + } + + if (m_supportsEGLImage && (m_isNewImage || m_targetTexture.m_textureId == GL_NO_TEXTURE)) { + if (m_targetTexture.m_textureId == GL_NO_TEXTURE) { + glGenTextures(1, &m_targetTexture.m_textureId); + } + GLUtils::createTextureFromEGLImage(m_targetTexture.m_textureId, m_eglImage); + LOGV("Generating Consumer Texture from 0x%x", m_eglImage); + m_isNewImage = false; + } + + return &m_targetTexture; +} + +void SharedTexture::releaseTarget() { + + if (m_supportsEGLFenceSyncKHR) { + if (m_syncObject != EGL_NO_SYNC_KHR) { + eglDestroySyncKHR(m_display, m_syncObject); + } + m_syncObject = eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, NULL); + } else { + // TODO the flush currently prevents the screen from getting partial + // updates but the only way to guarantee this is to call glFinish. Until + // we support an EGL sync we will leave flush enable in order to test + // with modest performance. + glFlush(); + } + + m_lock.unlock(); +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/android/SharedTexture.h b/WebCore/platform/graphics/android/SharedTexture.h new file mode 100644 index 0000000..88aecfc --- /dev/null +++ b/WebCore/platform/graphics/android/SharedTexture.h @@ -0,0 +1,134 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SharedTexture__DEFINED +#define SharedTexture__DEFINED + +#include <utils/threads.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> + +namespace WebCore { + +static const GLuint GL_NO_TEXTURE = 0; + +/** + * TextureInfo is a class that stores both the texture and metadata about the + * texture. + */ +class TextureInfo { +public: + + TextureInfo(); + + bool equalsAttributes(const TextureInfo* otherTexture); + void copyAttributes(const TextureInfo* sourceTexture); + + bool operator==(const TextureInfo& otherTexture); + + GLuint m_textureId; + uint32_t m_width; + uint32_t m_height; + GLenum m_internalFormat; +}; + +/** + * SharedTexture is a class that encapsulates all the necessary variables + * needed to share a single texture across threads. In the case that threads + * communicate using EGL's sharedContext mechanism or do not support the proper + * EGLImage extensions the targetTexture, eglImage, and isNewImage variables are + * not used. + */ +class SharedTexture { +public: + // consumer thread functions + SharedTexture(); + ~SharedTexture(); + + TextureInfo* lockSource(); + void releaseSource(); + + TextureInfo* lockTarget(); + void releaseTarget(); + + // these locks are only used for the methods below + void lock() { m_lock.lock(); } + void unlock() { m_lock.unlock(); } + + void initSourceTexture(); // producer thread only + GLuint getSourceTextureId() { return m_sourceTexture.m_textureId; } + GLuint getTargetTextureId() { return m_targetTexture.m_textureId; } + +private: + /** + * The mutex is used to ensure that the contents of the struct are current across + * threads and that only one thread is manipulating the texture at a given time. + */ + android::Mutex m_lock; + /** + * The texture and its associated metadata that is used by the producer. The + * texture is created in the producer's thread and can only be read by the + * consumer when the consumer shares the same context as the producer. The + * metadata is used to track changes to the texture that would orphan the + * target texture and require a new EGLImage to be constructed. + */ + TextureInfo m_sourceTexture; + /** + * The target texture stores the id and metadata of the texture that is to be + * used by the consumer. In the case where EGLImages are supported this hold + * the current eglImage target. + */ + TextureInfo m_targetTexture; + /** + * The EGLImage is used to share the texture between EGLContexts on two + * different threads. This serves as an alternative to sharing the contexts + * but is only used if GL and EGL support the required extensions. + */ + EGLImageKHR m_eglImage; + /** + * This flag is used to determine if the eglImage has been updated. This + * signals the consumer thread to rebind the targetTexture to the new image. + */ + bool m_isNewImage; + /** + * The sync allows the consumer to release the lock prior to the commands + * executing on the GPU. Prior to releasing the lock the consumer creates + * a sync object and stores it here. After locking the texture the client + * must check that the sync has completed prior to manipulating the texture. + * This value is only used if the proper EGL extensions are supported. + */ + EGLSyncKHR m_syncObject; + + EGLDisplay m_display; + + bool m_supportsEGLImage; + bool m_supportsEGLFenceSyncKHR; +}; + +} // namespace WebCore + +#endif // SharedTexture__DEFINED |