2 * Copyright 2010, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "SharedTexture.h"
31 #define LOG_TAG "SharedTexture.cpp"
32 #include <utils/Log.h>
36 TextureInfo::TextureInfo() {
37 m_textureId = GL_NO_TEXTURE;
43 bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) {
44 return otherTexture->m_width == m_width &&
45 otherTexture->m_height == m_height &&
46 otherTexture->m_internalFormat == m_internalFormat;
49 void TextureInfo::copyAttributes(const TextureInfo* sourceTexture) {
50 m_width = sourceTexture->m_width;
51 m_height = sourceTexture->m_height;
52 m_internalFormat = sourceTexture->m_internalFormat;
55 bool TextureInfo::operator==(const TextureInfo& otherTexture) {
56 return otherTexture.m_textureId == m_textureId && equalsAttributes(&otherTexture);
59 SharedTexture::SharedTexture() {
60 m_display = eglGetCurrentDisplay();
61 m_eglImage = EGL_NO_IMAGE_KHR;
63 m_syncObject = EGL_NO_SYNC_KHR;
64 m_supportsEGLImage = GLUtils::isEGLImageSupported();
65 m_supportsEGLFenceSyncKHR = GLUtils::isEGLFenceSyncSupported();
67 //TODO temporarily disable fence sync until nvidia implementation is complete
68 m_supportsEGLFenceSyncKHR = false;
70 LOGI("imageEGL: %d syncKHR: %d", m_supportsEGLImage, m_supportsEGLFenceSyncKHR);
73 // called by the consumer when it no longer wants to consume and after it has
74 // terminated all providers. It is up to the providers to terminate their
75 // textures in the case that EGLImages are used
76 SharedTexture::~SharedTexture() {
77 if (m_supportsEGLImage) {
78 eglDestroyImageKHR(m_display, m_eglImage);
79 glDeleteTextures(1, &m_targetTexture.m_textureId);
81 glDeleteTextures(1, &m_sourceTexture.m_textureId);
85 void SharedTexture::initSourceTexture() {
86 glGenTextures(1, &m_sourceTexture.m_textureId);
89 TextureInfo* SharedTexture::lockSource() {
92 if (m_supportsEGLFenceSyncKHR && m_syncObject != EGL_NO_SYNC_KHR) {
94 EGLint status = eglClientWaitSyncKHR(m_display, m_syncObject, 0, 1000000);
96 if (status == EGL_TIMEOUT_EXPIRED_KHR) {
97 LOGE("Sync timeout for shared texture (%d)", m_sourceTexture.m_textureId);
100 eglDestroySyncKHR(m_display, m_syncObject);
101 m_syncObject = EGL_NO_SYNC_KHR;
104 return &m_sourceTexture;
107 void SharedTexture::releaseSource() {
109 if (m_supportsEGLImage) {
110 // delete the existing image if needed
111 if (!m_sourceTexture.equalsAttributes(&m_targetTexture)) {
112 if (m_eglImage != EGL_NO_IMAGE_KHR) {
113 eglDestroyImageKHR(m_display, m_eglImage);
114 m_eglImage = EGL_NO_IMAGE_KHR;
117 m_targetTexture.copyAttributes(&m_sourceTexture);
120 // create an image from the texture
121 if (m_eglImage == EGL_NO_IMAGE_KHR) {
122 GLUtils::createEGLImageFromTexture(m_sourceTexture.m_textureId, &m_eglImage);
123 LOGV("Generating Image (%d) 0x%x", m_sourceTexture.m_textureId, m_eglImage);
126 glFinish(); // ensures the texture is ready to be used by the consumer
130 m_targetTexture = m_sourceTexture;
132 // in the case of shared contexts we must flush the texture edits to the
133 // GPU. This ensures the edits complete prior to allowing the texture to
134 // be bound on the producers context.
141 TextureInfo* SharedTexture::lockTarget() {
144 if ((!m_supportsEGLImage && m_targetTexture.m_textureId == GL_NO_TEXTURE) ||
145 (m_supportsEGLImage && m_eglImage == EGL_NO_IMAGE_KHR)) {
150 if (m_supportsEGLImage && (m_isNewImage || m_targetTexture.m_textureId == GL_NO_TEXTURE)) {
151 if (m_targetTexture.m_textureId == GL_NO_TEXTURE) {
152 glGenTextures(1, &m_targetTexture.m_textureId);
154 GLUtils::createTextureFromEGLImage(m_targetTexture.m_textureId, m_eglImage);
155 LOGV("Generating Consumer Texture from 0x%x", m_eglImage);
156 m_isNewImage = false;
159 return &m_targetTexture;
162 void SharedTexture::releaseTarget() {
164 if (m_supportsEGLFenceSyncKHR) {
165 if (m_syncObject != EGL_NO_SYNC_KHR) {
166 eglDestroySyncKHR(m_display, m_syncObject);
168 m_syncObject = eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, NULL);
170 // TODO the flush currently prevents the screen from getting partial
171 // updates but the only way to guarantee this is to call glFinish. Until
172 // we support an EGL sync we will leave flush enable in order to test
173 // with modest performance.
180 } // namespace WebCore