OSDN Git Service

Cleanup DoubleBufferedTexture and SharedTexture classes.
[android-x86/external-webkit.git] / WebCore / platform / graphics / android / SharedTexture.cpp
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 "SharedTexture.h"
28 #include "GLUtils.h"
29
30 #define LOG_NDEBUG 1
31 #define LOG_TAG "SharedTexture.cpp"
32 #include <utils/Log.h>
33
34 namespace WebCore {
35
36 TextureInfo::TextureInfo() {
37     m_textureId = GL_NO_TEXTURE;
38     m_width = 0;
39     m_height = 0;
40     m_internalFormat = 0;
41 }
42
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;
47 }
48
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;
53 }
54
55 bool TextureInfo::operator==(const TextureInfo& otherTexture) {
56     return otherTexture.m_textureId == m_textureId && equalsAttributes(&otherTexture);
57 }
58
59 SharedTexture::SharedTexture() {
60     m_display = eglGetCurrentDisplay();
61     m_eglImage = EGL_NO_IMAGE_KHR;
62     m_isNewImage = true;
63     m_syncObject = EGL_NO_SYNC_KHR;
64     m_supportsEGLImage = GLUtils::isEGLImageSupported();
65     m_supportsEGLFenceSyncKHR = GLUtils::isEGLFenceSyncSupported();
66
67     //TODO temporarily disable fence sync until nvidia implementation is complete
68     m_supportsEGLFenceSyncKHR = false;
69
70     LOGI("imageEGL: %d syncKHR: %d", m_supportsEGLImage, m_supportsEGLFenceSyncKHR);
71 }
72
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);
80     } else {
81         glDeleteTextures(1, &m_sourceTexture.m_textureId);
82     }
83 }
84
85 void SharedTexture::initSourceTexture() {
86     glGenTextures(1, &m_sourceTexture.m_textureId);
87 }
88
89 TextureInfo* SharedTexture::lockSource() {
90     m_lock.lock();
91
92     if (m_supportsEGLFenceSyncKHR && m_syncObject != EGL_NO_SYNC_KHR) {
93
94         EGLint status = eglClientWaitSyncKHR(m_display, m_syncObject, 0, 1000000);
95
96         if (status == EGL_TIMEOUT_EXPIRED_KHR) {
97             LOGE("Sync timeout for shared texture (%d)", m_sourceTexture.m_textureId);
98         }
99
100         eglDestroySyncKHR(m_display, m_syncObject);
101         m_syncObject = EGL_NO_SYNC_KHR;
102     }
103
104     return &m_sourceTexture;
105 }
106
107 void SharedTexture::releaseSource() {
108
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;
115                 m_isNewImage = true;
116             }
117             m_targetTexture.copyAttributes(&m_sourceTexture);
118         }
119
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);
124         }
125
126         glFinish(); // ensures the texture is ready to be used by the consumer
127
128     } else {
129
130         m_targetTexture = m_sourceTexture;
131
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.
135         glFlush();
136     }
137
138     m_lock.unlock();
139 }
140
141 TextureInfo* SharedTexture::lockTarget() {
142     m_lock.lock();
143
144     if ((!m_supportsEGLImage && m_targetTexture.m_textureId == GL_NO_TEXTURE) ||
145             (m_supportsEGLImage && m_eglImage == EGL_NO_IMAGE_KHR)) {
146         m_lock.unlock();
147         return 0;
148     }
149
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);
153         }
154         GLUtils::createTextureFromEGLImage(m_targetTexture.m_textureId, m_eglImage);
155         LOGV("Generating Consumer Texture from 0x%x", m_eglImage);
156         m_isNewImage = false;
157     }
158
159     return &m_targetTexture;
160 }
161
162 void SharedTexture::releaseTarget() {
163
164     if (m_supportsEGLFenceSyncKHR) {
165         if (m_syncObject != EGL_NO_SYNC_KHR) {
166             eglDestroySyncKHR(m_display, m_syncObject);
167         }
168         m_syncObject = eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, NULL);
169     } else {
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.
174         glFlush();
175     }
176
177     m_lock.unlock();
178 }
179
180 } // namespace WebCore