2
* Copyright (C) 2010 Apple Inc. All rights reserved.
3
* Copyright (C) 2010 Google Inc. All rights reserved.
4
* Copyright (C) 2011 Igalia S.L.
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
15
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
#include "GraphicsContextGLOpenGL.h"
31
#if ENABLE(GRAPHICS_CONTEXT_GL) && USE(TEXTURE_MAPPER)
33
#include "GraphicsContextGLOpenGLPrivate.h"
34
#include "TextureMapperGC3DPlatformLayer.h"
35
#include <ANGLE/ShaderLang.h>
36
#include <wtf/Deque.h>
37
#include <wtf/NeverDestroyed.h>
40
#define EGL_EGL_PROTOTYPES 0
41
// Skip the inclusion of ANGLE's explicit context entry points for now.
42
#define GL_ANGLE_explicit_context
43
#define GL_ANGLE_explicit_context_gles1
44
typedef void* GLeglContext;
45
#include <ANGLE/egl.h>
46
#include <ANGLE/eglext.h>
47
#include <ANGLE/eglext_angle.h>
48
#include <ANGLE/entry_points_egl.h>
49
#include <ANGLE/entry_points_gles_2_0_autogen.h>
50
#include <ANGLE/entry_points_gles_ext_autogen.h>
51
#include <ANGLE/gl2ext.h>
52
#include <ANGLE/gl2ext_angle.h>
65
#include "OpenGLShims.h"
69
#include "ExtensionsGLANGLE.h"
71
#include "ExtensionsGLOpenGLES.h"
73
#include "ExtensionsGLOpenGL.h"
78
#include "NicosiaGC3DANGLELayer.h"
80
#include "NicosiaGC3DLayer.h"
86
static const size_t MaxActiveContexts = 16;
87
static Deque<GraphicsContextGLOpenGL*, MaxActiveContexts>& activeContexts()
89
static NeverDestroyed<Deque<GraphicsContextGLOpenGL*, MaxActiveContexts>> s_activeContexts;
90
return s_activeContexts;
93
RefPtr<GraphicsContextGLOpenGL> GraphicsContextGLOpenGL::create(GraphicsContextGLAttributes attributes, HostWindow* hostWindow, GraphicsContextGLOpenGL::Destination destination)
95
// This implementation doesn't currently support rendering directly to the HostWindow.
96
if (destination == Destination::DirectlyToHostWindow)
99
static bool initialized = false;
100
static bool success = true;
102
#if !USE(OPENGL_ES) && !USE(LIBEPOXY) && !USE(ANGLE)
103
success = initializeOpenGLShims();
110
auto& contexts = activeContexts();
111
if (contexts.size() >= MaxActiveContexts)
112
contexts.first()->recycleContext();
114
// Calling recycleContext() above should have lead to the graphics context being
115
// destroyed and thus removed from the active contexts list.
116
if (contexts.size() >= MaxActiveContexts)
119
// Create the GraphicsContextGLOpenGL object first in order to establist a current context on this thread.
120
auto context = adoptRef(new GraphicsContextGLOpenGL(attributes, hostWindow, destination));
122
#if USE(LIBEPOXY) && USE(OPENGL_ES)
123
// Bail if GLES3 was requested but cannot be provided.
124
if (attributes.isWebGL2 && !epoxy_is_desktop_gl() && epoxy_gl_version() < 30)
128
contexts.append(context.get());
133
GraphicsContextGLOpenGL::GraphicsContextGLOpenGL(GraphicsContextGLAttributes attributes, HostWindow*, GraphicsContextGLOpenGL::Destination destination, GraphicsContextGLOpenGL* sharedContext)
134
: GraphicsContextGL(attributes, destination, sharedContext)
136
ASSERT_UNUSED(sharedContext, !sharedContext);
138
m_nicosiaLayer = WTF::makeUnique<Nicosia::GC3DANGLELayer>(*this, destination);
140
m_texmapLayer = WTF::makeUnique<TextureMapperGC3DPlatformLayer>(*this, destination);
142
makeContextCurrent();
144
validateAttributes();
145
attributes = contextAttributes(); // They may have changed during validation.
147
if (destination == Destination::Offscreen) {
148
// Create a texture to render into.
149
gl::GenTextures(1, &m_texture);
150
gl::BindTexture(GL_TEXTURE_RECTANGLE_ANGLE, m_texture);
151
gl::TexParameterf(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
152
gl::TexParameterf(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
153
gl::TexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
154
gl::TexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
155
gl::BindTexture(GL_TEXTURE_RECTANGLE_ANGLE, 0);
158
gl::GenFramebuffers(1, &m_fbo);
159
gl::BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
161
#if USE(COORDINATED_GRAPHICS)
162
gl::GenTextures(1, &m_compositorTexture);
163
gl::BindTexture(GL_TEXTURE_RECTANGLE_ANGLE, m_compositorTexture);
164
gl::TexParameterf(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
165
gl::TexParameterf(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
166
gl::TexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
167
gl::TexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
169
gl::GenTextures(1, &m_intermediateTexture);
170
gl::BindTexture(GL_TEXTURE_RECTANGLE_ANGLE, m_intermediateTexture);
171
gl::TexParameterf(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
172
gl::TexParameterf(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
173
gl::TexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
174
gl::TexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
176
gl::BindTexture(GL_TEXTURE_RECTANGLE_ANGLE, 0);
179
// Create a multisample FBO.
180
if (attributes.antialias) {
181
gl::GenFramebuffers(1, &m_multisampleFBO);
182
gl::BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
183
m_state.boundFBO = m_multisampleFBO;
184
gl::GenRenderbuffers(1, &m_multisampleColorBuffer);
185
if (attributes.stencil || attributes.depth)
186
gl::GenRenderbuffers(1, &m_multisampleDepthStencilBuffer);
189
gl::BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
190
m_state.boundFBO = m_fbo;
192
if (attributes.depth)
193
gl::GenRenderbuffers(1, &m_depthBuffer);
194
if (attributes.stencil)
195
gl::GenRenderbuffers(1, &m_stencilBuffer);
197
if (attributes.stencil || attributes.depth)
198
gl::GenRenderbuffers(1, &m_depthStencilBuffer);
202
gl::ClearColor(0, 0, 0, 0);
205
GraphicsContextGLOpenGL::GraphicsContextGLOpenGL(GraphicsContextGLAttributes attributes, HostWindow*, GraphicsContextGLOpenGL::Destination destination, GraphicsContextGLOpenGL* sharedContext)
206
: GraphicsContextGL(attributes, destination, sharedContext)
208
ASSERT_UNUSED(sharedContext, !sharedContext);
210
m_nicosiaLayer = makeUnique<Nicosia::GC3DLayer>(*this, destination);
212
m_texmapLayer = makeUnique<TextureMapperGC3DPlatformLayer>(*this, destination);
215
makeContextCurrent();
217
validateAttributes();
218
attributes = contextAttributes(); // They may have changed during validation.
220
if (destination == Destination::Offscreen) {
221
// Create a texture to render into.
222
::glGenTextures(1, &m_texture);
223
::glBindTexture(GL_TEXTURE_2D, m_texture);
224
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
225
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
226
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
227
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
228
::glBindTexture(GL_TEXTURE_2D, 0);
231
::glGenFramebuffers(1, &m_fbo);
232
::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
234
#if USE(COORDINATED_GRAPHICS)
235
::glGenTextures(1, &m_compositorTexture);
236
::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
237
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
238
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
239
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
240
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
242
::glGenTextures(1, &m_intermediateTexture);
243
::glBindTexture(GL_TEXTURE_2D, m_intermediateTexture);
244
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
245
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
246
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
247
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
249
::glBindTexture(GL_TEXTURE_2D, 0);
252
// Create a multisample FBO.
253
if (attributes.antialias) {
254
::glGenFramebuffers(1, &m_multisampleFBO);
255
::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
256
m_state.boundFBO = m_multisampleFBO;
257
::glGenRenderbuffers(1, &m_multisampleColorBuffer);
258
if (attributes.stencil || attributes.depth)
259
::glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer);
262
glBindFramebuffer(GraphicsContextGLOpenGL::FRAMEBUFFER, m_fbo);
263
m_state.boundFBO = m_fbo;
265
if (attributes.depth)
266
glGenRenderbuffers(1, &m_depthBuffer);
267
if (attributes.stencil)
268
glGenRenderbuffers(1, &m_stencilBuffer);
270
if (attributes.stencil || attributes.depth)
271
glGenRenderbuffers(1, &m_depthStencilBuffer);
276
::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
278
if (GLContext::current()->version() >= 320) {
279
m_usingCoreProfile = true;
281
// From version 3.2 on we use the OpenGL Core profile, so request that ouput to the shader compiler.
282
// OpenGL version 3.2 uses GLSL version 1.50.
283
m_compiler = ANGLEWebKitBridge(SH_GLSL_150_CORE_OUTPUT);
285
// From version 3.2 on we use the OpenGL Core profile, and we need a VAO for rendering.
286
// A VAO could be created and bound by each component using GL rendering (TextureMapper, WebGL, etc). This is
287
// a simpler solution: the first GraphicsContextGLOpenGL created on a GLContext will create and bind a VAO for that context.
288
GCGLint currentVAO = 0;
289
getIntegerv(GraphicsContextGLOpenGL::VERTEX_ARRAY_BINDING, ¤tVAO);
291
m_vao = createVertexArray();
292
bindVertexArray(m_vao);
295
// For lower versions request the compatibility output to the shader compiler.
296
m_compiler = ANGLEWebKitBridge(SH_GLSL_COMPATIBILITY_OUTPUT);
298
// GL_POINT_SPRITE is needed in lower versions.
299
::glEnable(GL_POINT_SPRITE);
302
// Adjust the shader specification depending on whether GLES3 (i.e. WebGL2 support) was requested.
303
m_compiler = ANGLEWebKitBridge(SH_ESSL_OUTPUT, attributes.isWebGL2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC);
306
// ANGLE initialization.
307
ShBuiltInResources ANGLEResources;
308
sh::InitBuiltInResources(&ANGLEResources);
310
getIntegerv(GraphicsContextGLOpenGL::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs);
311
getIntegerv(GraphicsContextGLOpenGL::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors);
312
getIntegerv(GraphicsContextGLOpenGL::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors);
313
getIntegerv(GraphicsContextGLOpenGL::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits);
314
getIntegerv(GraphicsContextGLOpenGL::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits);
315
getIntegerv(GraphicsContextGLOpenGL::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits);
316
getIntegerv(GraphicsContextGLOpenGL::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors);
318
// Always set to 1 for OpenGL ES.
319
ANGLEResources.MaxDrawBuffers = 1;
321
GCGLint range[2], precision;
322
getShaderPrecisionFormat(GraphicsContextGLOpenGL::FRAGMENT_SHADER, GraphicsContextGLOpenGL::HIGH_FLOAT, range, &precision);
323
ANGLEResources.FragmentPrecisionHigh = (range[0] || range[1] || precision);
325
m_compiler.setResources(ANGLEResources);
327
::glClearColor(0, 0, 0, 0);
332
GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL()
334
makeContextCurrent();
336
gl::DeleteTextures(1, &m_texture);
337
#if USE(COORDINATED_GRAPHICS)
338
if (m_compositorTexture)
339
gl::DeleteTextures(1, &m_compositorTexture);
342
auto attributes = contextAttributes();
344
if (attributes.antialias) {
345
gl::DeleteRenderbuffers(1, &m_multisampleColorBuffer);
346
if (attributes.stencil || attributes.depth)
347
gl::DeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer);
348
gl::DeleteFramebuffers(1, &m_multisampleFBO);
349
} else if (attributes.stencil || attributes.depth) {
352
glDeleteRenderbuffers(1, &m_depthBuffer);
355
glDeleteRenderbuffers(1, &m_stencilBuffer);
357
if (m_depthStencilBuffer)
358
gl::DeleteRenderbuffers(1, &m_depthStencilBuffer);
360
gl::DeleteFramebuffers(1, &m_fbo);
361
#if USE(COORDINATED_GRAPHICS)
362
gl::DeleteTextures(1, &m_intermediateTexture);
367
deleteVertexArray(m_vao);
370
auto* activeContext = activeContexts().takeLast([this](auto* it) {
373
ASSERT_UNUSED(activeContext, !!activeContext);
376
GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL()
378
makeContextCurrent();
380
::glDeleteTextures(1, &m_texture);
381
#if USE(COORDINATED_GRAPHICS)
382
if (m_compositorTexture)
383
::glDeleteTextures(1, &m_compositorTexture);
386
auto attributes = contextAttributes();
388
if (attributes.antialias) {
389
::glDeleteRenderbuffers(1, &m_multisampleColorBuffer);
390
if (attributes.stencil || attributes.depth)
391
::glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer);
392
::glDeleteFramebuffers(1, &m_multisampleFBO);
393
} else if (attributes.stencil || attributes.depth) {
396
glDeleteRenderbuffers(1, &m_depthBuffer);
399
glDeleteRenderbuffers(1, &m_stencilBuffer);
401
if (m_depthStencilBuffer)
402
::glDeleteRenderbuffers(1, &m_depthStencilBuffer);
404
::glDeleteFramebuffers(1, &m_fbo);
405
#if USE(COORDINATED_GRAPHICS)
406
::glDeleteTextures(1, &m_intermediateTexture);
411
deleteVertexArray(m_vao);
414
auto* activeContext = activeContexts().takeLast([this](auto* it) {
417
ASSERT_UNUSED(activeContext, !!activeContext);
421
bool GraphicsContextGLOpenGL::makeContextCurrent()
424
return m_nicosiaLayer->makeContextCurrent();
426
return m_texmapLayer->makeContextCurrent();
430
void GraphicsContextGLOpenGL::checkGPUStatus()
434
PlatformGraphicsContextGL GraphicsContextGLOpenGL::platformGraphicsContextGL() const
437
return m_nicosiaLayer->platformContext();
439
return m_texmapLayer->platformContext();
443
PlatformGLObject GraphicsContextGLOpenGL::platformTexture() const
448
bool GraphicsContextGLOpenGL::isGLES2Compliant() const
457
PlatformLayer* GraphicsContextGLOpenGL::platformLayer() const
460
return &m_nicosiaLayer->contentLayer();
462
return m_texmapLayer.get();
466
#if PLATFORM(GTK) && !USE(ANGLE)
467
ExtensionsGL& GraphicsContextGLOpenGL::getExtensions()
471
// glGetStringi is not available on GLES2.
472
m_extensions = makeUnique<ExtensionsGLOpenGLES>(this, false);
474
// From OpenGL 3.2 on we use the Core profile, and there we must use glGetStringi.
475
m_extensions = makeUnique<ExtensionsGLOpenGL>(this, GLContext::current()->version() >= 320);
478
return *m_extensions;
482
} // namespace WebCore
484
#endif // ENABLE(GRAPHICS_CONTEXT_GL) && USE(TEXTURE_MAPPER)