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#include "FloatRect.h" 30 31#if USE(GLX) 32#include "GLXSurface.h" 33#endif 34 35#if USE(EGL) 36#include "EGLSurface.h" 37#endif 38 39#include <texmap/TextureMapperShaderProgram.h> 40 41namespace WebCore { 42 43static const GLfloat vertices[] = { 0, 0, 1, 0, 1, 1, 0, 1 }; 44static bool vertexArrayObjectSupported = false; 45 46PassOwnPtr<GLTransportSurface> GLTransportSurface::createTransportSurface(const IntSize& size, SurfaceAttributes attributes) 47{ 48 OwnPtr<GLTransportSurface> surface; 49#if USE(GLX) 50 surface = adoptPtr(new GLXTransportSurface(size, attributes)); 51#elif USE(EGL) 52 surface = EGLTransportSurface::createTransportSurface(size, attributes); 53#endif 54 55 if (surface && surface->handle() && surface->drawable()) 56 return surface.release(); 57 58 return nullptr; 59} 60 61GLTransportSurface::GLTransportSurface(const IntSize& size, SurfaceAttributes attributes) 62 : GLPlatformSurface(attributes) 63 , m_vbo(0) 64 , m_vertexHandle(0) 65 , m_boundTexture(0) 66{ 67 m_rect = IntRect(IntPoint(), size); 68} 69 70GLTransportSurface::~GLTransportSurface() 71{ 72} 73 74void GLTransportSurface::updateContents(const uint32_t texture) 75{ 76 if (!m_shaderProgram) 77 initializeShaderProgram(); 78 79 draw(texture); 80 swapBuffers(); 81} 82 83void GLTransportSurface::setGeometry(const IntRect& newRect) 84{ 85 m_rect = newRect; 86 87 if (!m_shaderProgram) 88 return; 89 90 updateTransformationMatrix(); 91} 92 93void GLTransportSurface::destroy() 94{ 95 m_rect = IntRect(); 96 97 if (!m_shaderProgram || !m_context3D) 98 return; 99 100 ::glBindFramebuffer(GL_FRAMEBUFFER, 0); 101 ::glBindTexture(GL_TEXTURE_2D, 0); 102 ::glBindBuffer(GL_ARRAY_BUFFER, 0); 103 104 if (m_vbo) 105 ::glDeleteBuffers(1, &m_vbo); 106 107 if (m_vertexHandle) { 108 m_context3D->getExtensions()->bindVertexArrayOES(0); 109 m_context3D->getExtensions()->deleteVertexArrayOES(m_vertexHandle); 110 } else if (m_shaderProgram) 111 ::glDisableVertexAttribArray(m_shaderProgram->vertexLocation()); 112 113 ::glUseProgram(0); 114 115 m_shaderProgram = nullptr; 116 m_context3D = nullptr; 117 m_boundTexture = 0; 118} 119 120void GLTransportSurface::draw(const uint32_t texture) 121{ 122 if (!m_vertexHandle) 123 bindArrayBuffer(); 124 125 if (m_boundTexture != texture) { 126 ::glBindTexture(GL_TEXTURE_2D, texture); 127 m_boundTexture = texture; 128 } 129 130 ::glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 131} 132 133void GLTransportSurface::bindArrayBuffer() const 134{ 135 ::glEnableVertexAttribArray(m_shaderProgram->vertexLocation()); 136 ::glBindBuffer(GL_ARRAY_BUFFER, m_vbo); 137 ::glVertexAttribPointer(m_shaderProgram->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0); 138} 139 140void GLTransportSurface::updateTransformationMatrix() 141{ 142 if (!m_shaderProgram) 143 return; 144 145 ::glViewport(m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height()); 146 m_boundTexture = 0; 147 148 FloatRect targetRect = FloatRect(m_rect); 149 TransformationMatrix identityMatrix; 150 TransformationMatrix matrix = TransformationMatrix(identityMatrix).multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect)); 151 m_shaderProgram->setMatrix(m_shaderProgram->modelViewMatrixLocation(), matrix); 152 153 // Taken from TextureMapperGL. 154 const float nearValue = 9999999; 155 const float farValue = -99999; 156 157 TransformationMatrix projectionMatrix = TransformationMatrix(2.0 / float(m_rect.width()), 0, 0, 0, 158 0, (-2.0) / float(m_rect.height()), 0, 0, 159 0, 0, -2.f / (farValue - nearValue), 0, 160 -1, 1, -(farValue + nearValue) / (farValue - nearValue), 1); 161 162 m_shaderProgram->setMatrix(m_shaderProgram->projectionMatrixLocation(), projectionMatrix); 163} 164 165void GLTransportSurface::initializeShaderProgram() 166{ 167 if (!m_context3D) 168 m_context3D = GraphicsContext3D::createForCurrentGLContext(); 169 170 vertexArrayObjectSupported = m_context3D->getExtensions()->supports("GL_OES_vertex_array_object"); 171 172 TextureMapperShaderProgram::Options options = TextureMapperShaderProgram::Texture; 173 m_shaderProgram = TextureMapperShaderProgram::create(m_context3D, options); 174 175 ::glUseProgram(m_shaderProgram->programID()); 176 ::glUniform1i(m_shaderProgram->samplerLocation(), 0); 177 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 178 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 179 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 180 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 181 182 TransformationMatrix flipTransform; 183 flipTransform.flipY(); 184 flipTransform.translate(0, -1); 185 m_shaderProgram->setMatrix(m_shaderProgram->textureSpaceMatrixLocation(), flipTransform); 186 187 ::glUniform1f(m_shaderProgram->opacityLocation(), 1.0); 188 189 if (!m_vbo) { 190 ::glGenBuffers(1, &m_vbo); 191 ::glBindBuffer(GL_ARRAY_BUFFER, m_vbo); 192 ::glBufferData(GL_ARRAY_BUFFER, sizeof(GC3Dfloat) * 8, vertices, GL_STATIC_DRAW); 193 } 194 195 // Create and set-up vertex array object. 196 if (vertexArrayObjectSupported) { 197 m_vertexHandle = m_context3D->getExtensions()->createVertexArrayOES(); 198 199 if (m_vertexHandle) { 200 m_context3D->getExtensions()->bindVertexArrayOES(m_vertexHandle); 201 bindArrayBuffer(); 202 } 203 } 204 205 updateTransformationMatrix(); 206} 207 208PassOwnPtr<GLTransportSurfaceClient> GLTransportSurfaceClient::createTransportSurfaceClient(const PlatformBufferHandle handle, const IntSize& size, bool hasAlpha) 209{ 210 OwnPtr<GLTransportSurfaceClient> client; 211#if USE(GLX) 212 client = adoptPtr(new GLXTransportSurfaceClient(handle, hasAlpha)); 213 UNUSED_PARAM(size); 214#else 215 client = EGLTransportSurface::createTransportSurfaceClient(handle, size, hasAlpha); 216#endif 217 218 if (!client || !client->texture()) { 219 LOG_ERROR("Failed to Create Transport Surface client."); 220 return nullptr; 221 } 222 223 return client.release(); 224} 225 226 227GLTransportSurfaceClient::GLTransportSurfaceClient() 228 : m_texture(0) 229{ 230} 231 232GLTransportSurfaceClient::~GLTransportSurfaceClient() 233{ 234} 235 236void GLTransportSurfaceClient::destroy() 237{ 238 if (m_texture) { 239 glBindTexture(GL_TEXTURE_2D, 0); 240 glDeleteTextures(1, &m_texture); 241 m_texture = 0; 242 } 243} 244 245void GLTransportSurfaceClient::prepareTexture() 246{ 247} 248 249void GLTransportSurfaceClient::createTexture() 250{ 251 ::glGenTextures(1, &m_texture); 252 ::glBindTexture(GL_TEXTURE_2D, m_texture); 253 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 254 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 255 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 256 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 257} 258 259} 260