1/* 2 * Copyright (C) 2013 Intel Corporation. All rights reserved. 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 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "GLTransportSurface.h" 28 29#if USE(ACCELERATED_COMPOSITING) 30 31#include "FloatRect.h" 32 33#if USE(GLX) 34#include "GLXSurface.h" 35#endif 36 37#if USE(EGL) 38#include "EGLSurface.h" 39#endif 40 41#include <texmap/TextureMapperShaderProgram.h> 42 43namespace WebCore { 44 45static const GLfloat vertices[] = { 0, 0, 1, 0, 1, 1, 0, 1 }; 46static bool vertexArrayObjectSupported = false; 47 48PassOwnPtr<GLTransportSurface> GLTransportSurface::createTransportSurface(const IntSize& size, SurfaceAttributes attributes) 49{ 50 OwnPtr<GLTransportSurface> surface; 51#if USE(GLX) 52 surface = adoptPtr(new GLXTransportSurface(size, attributes)); 53#elif USE(EGL) 54 surface = EGLTransportSurface::createTransportSurface(size, attributes); 55#endif 56 57 if (surface && surface->handle() && surface->drawable()) 58 return surface.release(); 59 60 return nullptr; 61} 62 63GLTransportSurface::GLTransportSurface(const IntSize& size, SurfaceAttributes attributes) 64 : GLPlatformSurface(attributes) 65 , m_vbo(0) 66 , m_vertexHandle(0) 67 , m_boundTexture(0) 68{ 69 m_rect = IntRect(IntPoint(), size); 70} 71 72GLTransportSurface::~GLTransportSurface() 73{ 74} 75 76void GLTransportSurface::updateContents(const uint32_t texture) 77{ 78 if (!m_shaderProgram) 79 initializeShaderProgram(); 80 81 draw(texture); 82 swapBuffers(); 83} 84 85void GLTransportSurface::setGeometry(const IntRect& newRect) 86{ 87 m_rect = newRect; 88 89 if (!m_shaderProgram) 90 return; 91 92 updateTransformationMatrix(); 93} 94 95void GLTransportSurface::destroy() 96{ 97 m_rect = IntRect(); 98 99 if (!m_shaderProgram || !m_context3D) 100 return; 101 102 ::glBindFramebuffer(GL_FRAMEBUFFER, 0); 103 ::glBindTexture(GL_TEXTURE_2D, 0); 104 ::glBindBuffer(GL_ARRAY_BUFFER, 0); 105 106 if (m_vbo) 107 ::glDeleteBuffers(1, &m_vbo); 108 109 if (m_vertexHandle) { 110 m_context3D->getExtensions()->bindVertexArrayOES(0); 111 m_context3D->getExtensions()->deleteVertexArrayOES(m_vertexHandle); 112 } else if (m_shaderProgram) 113 ::glDisableVertexAttribArray(m_shaderProgram->vertexLocation()); 114 115 ::glUseProgram(0); 116 117 m_shaderProgram = nullptr; 118 m_context3D = nullptr; 119 m_boundTexture = 0; 120} 121 122void GLTransportSurface::draw(const uint32_t texture) 123{ 124 if (!m_vertexHandle) 125 bindArrayBuffer(); 126 127 if (m_boundTexture != texture) { 128 ::glBindTexture(GL_TEXTURE_2D, texture); 129 m_boundTexture = texture; 130 } 131 132 ::glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 133} 134 135void GLTransportSurface::bindArrayBuffer() const 136{ 137 ::glEnableVertexAttribArray(m_shaderProgram->vertexLocation()); 138 ::glBindBuffer(GL_ARRAY_BUFFER, m_vbo); 139 ::glVertexAttribPointer(m_shaderProgram->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0); 140} 141 142void GLTransportSurface::updateTransformationMatrix() 143{ 144 if (!m_shaderProgram) 145 return; 146 147 ::glViewport(m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height()); 148 m_boundTexture = 0; 149 150 FloatRect targetRect = FloatRect(m_rect); 151 TransformationMatrix identityMatrix; 152 TransformationMatrix matrix = TransformationMatrix(identityMatrix).multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect)); 153 m_shaderProgram->setMatrix(m_shaderProgram->modelViewMatrixLocation(), matrix); 154 155 // Taken from TextureMapperGL. 156 const float nearValue = 9999999; 157 const float farValue = -99999; 158 159 TransformationMatrix projectionMatrix = TransformationMatrix(2.0 / float(m_rect.width()), 0, 0, 0, 160 0, (-2.0) / float(m_rect.height()), 0, 0, 161 0, 0, -2.f / (farValue - nearValue), 0, 162 -1, 1, -(farValue + nearValue) / (farValue - nearValue), 1); 163 164 m_shaderProgram->setMatrix(m_shaderProgram->projectionMatrixLocation(), projectionMatrix); 165} 166 167void GLTransportSurface::initializeShaderProgram() 168{ 169 if (!m_context3D) 170 m_context3D = GraphicsContext3D::createForCurrentGLContext(); 171 172 vertexArrayObjectSupported = m_context3D->getExtensions()->supports("GL_OES_vertex_array_object"); 173 174 TextureMapperShaderProgram::Options options = TextureMapperShaderProgram::Texture; 175 m_shaderProgram = TextureMapperShaderProgram::create(m_context3D, options); 176 177 ::glUseProgram(m_shaderProgram->programID()); 178 ::glUniform1i(m_shaderProgram->samplerLocation(), 0); 179 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 180 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 181 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 182 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 183 184 TransformationMatrix flipTransform; 185 flipTransform.flipY(); 186 flipTransform.translate(0, -1); 187 m_shaderProgram->setMatrix(m_shaderProgram->textureSpaceMatrixLocation(), flipTransform); 188 189 ::glUniform1f(m_shaderProgram->opacityLocation(), 1.0); 190 191 if (!m_vbo) { 192 ::glGenBuffers(1, &m_vbo); 193 ::glBindBuffer(GL_ARRAY_BUFFER, m_vbo); 194 ::glBufferData(GL_ARRAY_BUFFER, sizeof(GC3Dfloat) * 8, vertices, GL_STATIC_DRAW); 195 } 196 197 // Create and set-up vertex array object. 198 if (vertexArrayObjectSupported) { 199 m_vertexHandle = m_context3D->getExtensions()->createVertexArrayOES(); 200 201 if (m_vertexHandle) { 202 m_context3D->getExtensions()->bindVertexArrayOES(m_vertexHandle); 203 bindArrayBuffer(); 204 } 205 } 206 207 updateTransformationMatrix(); 208} 209 210PassOwnPtr<GLTransportSurfaceClient> GLTransportSurfaceClient::createTransportSurfaceClient(const PlatformBufferHandle handle, const IntSize& size, bool hasAlpha) 211{ 212 OwnPtr<GLTransportSurfaceClient> client; 213#if USE(GLX) 214 client = adoptPtr(new GLXTransportSurfaceClient(handle, hasAlpha)); 215 UNUSED_PARAM(size); 216#else 217 client = EGLTransportSurface::createTransportSurfaceClient(handle, size, hasAlpha); 218#endif 219 220 if (!client || !client->texture()) { 221 LOG_ERROR("Failed to Create Transport Surface client."); 222 return nullptr; 223 } 224 225 return client.release(); 226} 227 228 229GLTransportSurfaceClient::GLTransportSurfaceClient() 230 : m_texture(0) 231{ 232} 233 234GLTransportSurfaceClient::~GLTransportSurfaceClient() 235{ 236} 237 238void GLTransportSurfaceClient::destroy() 239{ 240 if (m_texture) { 241 glBindTexture(GL_TEXTURE_2D, 0); 242 glDeleteTextures(1, &m_texture); 243 m_texture = 0; 244 } 245} 246 247void GLTransportSurfaceClient::prepareTexture() 248{ 249} 250 251void GLTransportSurfaceClient::createTexture() 252{ 253 ::glGenTextures(1, &m_texture); 254 ::glBindTexture(GL_TEXTURE_2D, m_texture); 255 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 256 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 257 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 258 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 259} 260 261} 262 263#endif 264