summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebCore/platform/graphics/android/DoubleBufferedTexture.cpp150
-rw-r--r--WebCore/platform/graphics/android/DoubleBufferedTexture.h75
-rw-r--r--WebCore/platform/graphics/android/GLUtils.cpp29
-rw-r--r--WebCore/platform/graphics/android/GLUtils.h8
-rw-r--r--WebCore/platform/graphics/android/SharedTexture.cpp185
-rw-r--r--WebCore/platform/graphics/android/SharedTexture.h134
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