Replace WTF::move with WTFMove
[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 #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
41 namespace WebCore {
42
43 static const GLfloat vertices[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
44 static bool vertexArrayObjectSupported = false;
45
46 std::unique_ptr<GLTransportSurface> GLTransportSurface::createTransportSurface(const IntSize& size, SurfaceAttributes attributes)
47 {
48     std::unique_ptr<GLTransportSurface> surface;
49 #if USE(GLX)
50     surface = std::make_unique<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 WTFMove(surface);
57
58     return nullptr;
59 }
60
61 GLTransportSurface::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
70 GLTransportSurface::~GLTransportSurface()
71 {
72 }
73
74 void GLTransportSurface::updateContents(const uint32_t texture)
75 {
76     if (!m_shaderProgram)
77         initializeShaderProgram();
78
79     draw(texture);
80     swapBuffers();
81 }
82
83 void GLTransportSurface::setGeometry(const IntRect& newRect)
84 {
85     m_rect = newRect;
86
87     if (!m_shaderProgram)
88         return;
89
90     updateTransformationMatrix();
91 }
92
93 void 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
120 void 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
133 void 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
140 void 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
165 void 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
208 std::unique_ptr<GLTransportSurfaceClient> GLTransportSurfaceClient::createTransportSurfaceClient(const PlatformBufferHandle handle, const IntSize& size, bool hasAlpha)
209 {
210     std::unique_ptr<GLTransportSurfaceClient> client;
211 #if USE(GLX)
212     client = std::make_unique<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 WTFMove(client);
224 }
225
226
227 GLTransportSurfaceClient::GLTransportSurfaceClient()
228     : m_texture(0)
229 {
230 }
231
232 GLTransportSurfaceClient::~GLTransportSurfaceClient()
233 {
234 }
235
236 void 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
245 void GLTransportSurfaceClient::prepareTexture()
246 {
247 }
248
249 void 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 }