[EFL][WebGL] Refactor GLPlatformSurface.
[WebKit-https.git] / Source / WebCore / platform / graphics / surfaces / GLTransportSurface.cpp
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 namespace WebCore {
32
33 static const GLfloat vertices[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
34 static bool vertexArrayObjectSupported = false;
35
36 GLTransportSurface::GLTransportSurface(SurfaceAttributes attributes)
37     : GLPlatformSurface(attributes)
38     , m_vbo(0)
39     , m_vertexHandle(0)
40 {
41 }
42
43 GLTransportSurface::~GLTransportSurface()
44 {
45 }
46
47 void GLTransportSurface::updateContents(const uint32_t texture)
48 {
49     if (!m_shaderProgram)
50         initializeShaderProgram();
51
52     draw(texture);
53     swapBuffers();
54 }
55
56 void GLTransportSurface::setGeometry(const IntRect& newRect)
57 {
58     m_rect = newRect;
59
60     if (!m_shaderProgram)
61         return;
62
63     updateTransformationMatrix();
64 }
65
66 void GLTransportSurface::destroy()
67 {
68     m_rect = IntRect();
69
70     ::glBindFramebuffer(GL_FRAMEBUFFER, 0);
71     ::glBindTexture(GL_TEXTURE_2D, 0);
72
73     if (!m_shaderProgram || !m_context3D)
74         return;
75
76     ::glBindBuffer(GL_ARRAY_BUFFER, 0);
77
78     if (m_vbo)
79         ::glDeleteBuffers(1, &m_vbo);
80
81     if (m_vertexHandle) {
82         m_context3D->getExtensions()->bindVertexArrayOES(0);
83         m_context3D->getExtensions()->deleteVertexArrayOES(m_vertexHandle);
84     } else if (m_shaderProgram)
85         ::glDisableVertexAttribArray(m_shaderProgram->vertexLocation());
86
87     ::glUseProgram(0);
88
89     m_shaderProgram = nullptr;
90     m_context3D = nullptr;
91 }
92
93 void GLTransportSurface::draw(const uint32_t texture)
94 {
95     if (!m_vertexHandle)
96         bindArrayBuffer();
97
98     ::glBindTexture(GL_TEXTURE_2D, texture);
99     ::glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
100 }
101
102 void GLTransportSurface::bindArrayBuffer() const
103 {
104     ::glEnableVertexAttribArray(m_shaderProgram->vertexLocation());
105     ::glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
106     ::glVertexAttribPointer(m_shaderProgram->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0);
107 }
108
109 void GLTransportSurface::updateTransformationMatrix()
110 {
111     if (!m_shaderProgram)
112         return;
113
114     ::glViewport(m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height());
115
116     FloatRect targetRect = FloatRect(m_rect);
117     TransformationMatrix identityMatrix;
118     TransformationMatrix matrix = TransformationMatrix(identityMatrix).multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect));
119     m_shaderProgram->setMatrix(m_shaderProgram->modelViewMatrixLocation(), matrix);
120
121     // Taken from TextureMapperGL.
122     const float nearValue = 9999999;
123     const float farValue = -99999;
124
125     TransformationMatrix projectionMatrix = TransformationMatrix(2.0 / float(m_rect.width()), 0, 0, 0,
126         0, (-2.0) / float(m_rect.height()), 0, 0,
127         0, 0, -2.f / (farValue - nearValue), 0,
128         -1, 1, -(farValue + nearValue) / (farValue - nearValue), 1);
129
130     m_shaderProgram->setMatrix(m_shaderProgram->projectionMatrixLocation(), projectionMatrix);
131 }
132
133 void GLTransportSurface::initializeShaderProgram()
134 {
135     if (!m_context3D)
136         m_context3D = GraphicsContext3D::createForCurrentGLContext();
137
138     vertexArrayObjectSupported = m_context3D->getExtensions()->supports("GL_OES_vertex_array_object");
139
140     TextureMapperShaderProgram::Options options = TextureMapperShaderProgram::Texture;
141     m_shaderProgram = TextureMapperShaderProgram::create(m_context3D, options);
142
143     ::glUseProgram(m_shaderProgram->programID());
144     ::glUniform1i(m_shaderProgram->samplerLocation(), 0);
145     ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
146     ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
147     ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
148     ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
149
150     TransformationMatrix flipTransform;
151     flipTransform.flipY();
152     flipTransform.translate(0, -1);
153     m_shaderProgram->setMatrix(m_shaderProgram->textureSpaceMatrixLocation(), flipTransform);
154
155     ::glUniform1f(m_shaderProgram->opacityLocation(), 1.0);
156
157     if (!m_vbo) {
158         ::glGenBuffers(1, &m_vbo);
159         ::glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
160         ::glBufferData(GL_ARRAY_BUFFER, sizeof(GC3Dfloat) * 8, vertices, GL_STATIC_DRAW);
161     }
162
163     // Create and set-up vertex array object.
164     if (vertexArrayObjectSupported) {
165         m_vertexHandle = m_context3D->getExtensions()->createVertexArrayOES();
166
167         if (m_vertexHandle) {
168             m_context3D->getExtensions()->bindVertexArrayOES(m_vertexHandle);
169             bindArrayBuffer();
170         }
171     }
172
173     updateTransformationMatrix();
174
175     ::glBindFramebuffer(GL_FRAMEBUFFER, 0);
176 }
177
178 }
179
180 #endif
181