1/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28
29#if ENABLE(GRAPHICS_CONTEXT_3D)
30#include "Extensions3DOpenGLCommon.h"
31
32#include "ANGLEWebKitBridge.h"
33#include "GraphicsContext3D.h"
34
35#if PLATFORM(COCOA)
36
37#if USE(OPENGL_ES)
38#include <OpenGLES/ES2/glext.h>
39#include <OpenGLES/ES3/gl.h>
40#else
41#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
42#include <OpenGL/gl.h>
43#include <OpenGL/gl3.h>
44#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
45#endif
46
47#else
48
49#if USE(LIBEPOXY)
50#include "EpoxyShims.h"
51#elif USE(OPENGL_ES)
52#include "OpenGLESShims.h"
53#include <GLES2/gl2.h>
54#include <GLES2/gl2ext.h>
55#elif PLATFORM(GTK) || PLATFORM(WIN)
56#include "OpenGLShims.h"
57#endif
58
59#endif
60
61#include <wtf/MainThread.h>
62#include <wtf/Vector.h>
63
64namespace WebCore {
65
66Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context, bool useIndexedGetString)
67 : m_initializedAvailableExtensions(false)
68 , m_context(context)
69 , m_isNVIDIA(false)
70 , m_isAMD(false)
71 , m_isIntel(false)
72 , m_isImagination(false)
73 , m_requiresBuiltInFunctionEmulation(false)
74 , m_requiresRestrictedMaximumTextureSize(false)
75 , m_useIndexedGetString(useIndexedGetString)
76{
77 m_vendor = String(reinterpret_cast<const char*>(::glGetString(GL_VENDOR)));
78 m_renderer = String(reinterpret_cast<const char*>(::glGetString(GL_RENDERER)));
79
80 Vector<String> vendorComponents = m_vendor.convertToASCIILowercase().split(' ');
81 if (vendorComponents.contains("nvidia"))
82 m_isNVIDIA = true;
83 if (vendorComponents.contains("ati") || vendorComponents.contains("amd"))
84 m_isAMD = true;
85 if (vendorComponents.contains("intel"))
86 m_isIntel = true;
87 if (vendorComponents.contains("imagination"))
88 m_isImagination = true;
89
90#if PLATFORM(MAC)
91 if (m_isAMD || m_isIntel)
92 m_requiresBuiltInFunctionEmulation = true;
93
94 // Intel HD 3000 devices have problems with large textures. <rdar://problem/16649140>
95 m_requiresRestrictedMaximumTextureSize = m_renderer.startsWith("Intel HD Graphics 3000");
96#endif
97}
98
99Extensions3DOpenGLCommon::~Extensions3DOpenGLCommon() = default;
100
101bool Extensions3DOpenGLCommon::supports(const String& name)
102{
103 if (!m_initializedAvailableExtensions)
104 initializeAvailableExtensions();
105
106 // We explicitly do not support this extension until
107 // we fix the following bug:
108 // https://bugs.webkit.org/show_bug.cgi?id=149734
109 if (name == "GL_ANGLE_translated_shader_source")
110 return false;
111
112 return supportsExtension(name);
113}
114
115void Extensions3DOpenGLCommon::ensureEnabled(const String& name)
116{
117 if (name == "GL_OES_standard_derivatives") {
118 // Enable support in ANGLE (if not enabled already)
119 ANGLEWebKitBridge& compiler = m_context->m_compiler;
120 ShBuiltInResources ANGLEResources = compiler.getResources();
121 if (!ANGLEResources.OES_standard_derivatives) {
122 ANGLEResources.OES_standard_derivatives = 1;
123 compiler.setResources(ANGLEResources);
124 }
125 } else if (name == "GL_EXT_draw_buffers") {
126 // Enable support in ANGLE (if not enabled already)
127 ANGLEWebKitBridge& compiler = m_context->m_compiler;
128 ShBuiltInResources ANGLEResources = compiler.getResources();
129 if (!ANGLEResources.EXT_draw_buffers) {
130 ANGLEResources.EXT_draw_buffers = 1;
131 m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &ANGLEResources.MaxDrawBuffers);
132 compiler.setResources(ANGLEResources);
133 }
134 } else if (name == "GL_EXT_shader_texture_lod") {
135 // Enable support in ANGLE (if not enabled already)
136 ANGLEWebKitBridge& compiler = m_context->m_compiler;
137 ShBuiltInResources ANGLEResources = compiler.getResources();
138 if (!ANGLEResources.EXT_shader_texture_lod) {
139 ANGLEResources.EXT_shader_texture_lod = 1;
140 compiler.setResources(ANGLEResources);
141 }
142 } else if (name == "GL_EXT_frag_depth") {
143 // Enable support in ANGLE (if not enabled already)
144 ANGLEWebKitBridge& compiler = m_context->m_compiler;
145 ShBuiltInResources ANGLEResources = compiler.getResources();
146 if (!ANGLEResources.EXT_frag_depth) {
147 ANGLEResources.EXT_frag_depth = 1;
148 compiler.setResources(ANGLEResources);
149 }
150 }
151}
152
153bool Extensions3DOpenGLCommon::isEnabled(const String& name)
154{
155 if (name == "GL_OES_standard_derivatives") {
156 ANGLEWebKitBridge& compiler = m_context->m_compiler;
157 return compiler.getResources().OES_standard_derivatives;
158 }
159 return supports(name);
160}
161
162int Extensions3DOpenGLCommon::getGraphicsResetStatusARB()
163{
164 return GraphicsContext3D::NO_ERROR;
165}
166
167String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject shader)
168{
169 ASSERT(shader);
170 int GLshaderType;
171 ANGLEShaderType shaderType;
172
173 ANGLEWebKitBridge& compiler = m_context->m_compiler;
174
175 m_context->getShaderiv(shader, GraphicsContext3D::SHADER_TYPE, &GLshaderType);
176
177 if (GLshaderType == GraphicsContext3D::VERTEX_SHADER)
178 shaderType = SHADER_TYPE_VERTEX;
179 else if (GLshaderType == GraphicsContext3D::FRAGMENT_SHADER)
180 shaderType = SHADER_TYPE_FRAGMENT;
181 else
182 return ""; // Invalid shader type.
183
184 HashMap<Platform3DObject, GraphicsContext3D::ShaderSourceEntry>::iterator result = m_context->m_shaderSourceMap.find(shader);
185
186 if (result == m_context->m_shaderSourceMap.end())
187 return "";
188
189 GraphicsContext3D::ShaderSourceEntry& entry = result->value;
190
191 String translatedShaderSource;
192 String shaderInfoLog;
193 uint64_t extraCompileOptions = SH_CLAMP_INDIRECT_ARRAY_BOUNDS | SH_UNFOLD_SHORT_CIRCUIT | SH_INIT_OUTPUT_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS | SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH | SH_INITIALIZE_UNINITIALIZED_LOCALS;
194
195 if (m_requiresBuiltInFunctionEmulation)
196 extraCompileOptions |= SH_EMULATE_ABS_INT_FUNCTION;
197
198 Vector<std::pair<ANGLEShaderSymbolType, sh::ShaderVariable>> symbols;
199 bool isValid = compiler.compileShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, symbols, extraCompileOptions);
200
201 entry.log = shaderInfoLog;
202 entry.isValid = isValid;
203
204 for (const std::pair<ANGLEShaderSymbolType, sh::ShaderVariable>& pair : symbols) {
205 const std::string& name = pair.second.name;
206 entry.symbolMap(pair.first).set(String(name.c_str(), name.length()), pair.second);
207 }
208
209 if (!isValid)
210 return "";
211
212 return translatedShaderSource;
213}
214
215void Extensions3DOpenGLCommon::initializeAvailableExtensions()
216{
217#if (PLATFORM(COCOA) && USE(OPENGL)) || (PLATFORM(GTK) && !USE(OPENGL_ES))
218 if (m_useIndexedGetString) {
219 GLint numExtensions = 0;
220 ::glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
221 for (GLint i = 0; i < numExtensions; ++i)
222 m_availableExtensions.add(glGetStringi(GL_EXTENSIONS, i));
223
224 if (!m_availableExtensions.contains("GL_ARB_texture_storage"_s)) {
225 GLint majorVersion;
226 glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
227 GLint minorVersion;
228 glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
229 if (majorVersion > 4 || (majorVersion == 4 && minorVersion >= 2))
230 m_availableExtensions.add("GL_ARB_texture_storage"_s);
231 }
232 } else
233#endif
234 {
235 String extensionsString = getExtensions();
236 for (auto& extension : extensionsString.split(' '))
237 m_availableExtensions.add(extension);
238 }
239 m_initializedAvailableExtensions = true;
240}
241
242void Extensions3DOpenGLCommon::readnPixelsEXT(int, int, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, GC3Dsizei, void *)
243{
244 m_context->synthesizeGLError(GL_INVALID_OPERATION);
245}
246
247void Extensions3DOpenGLCommon::getnUniformfvEXT(GC3Duint, int, GC3Dsizei, float *)
248{
249 m_context->synthesizeGLError(GL_INVALID_OPERATION);
250}
251
252void Extensions3DOpenGLCommon::getnUniformivEXT(GC3Duint, int, GC3Dsizei, int *)
253{
254 m_context->synthesizeGLError(GL_INVALID_OPERATION);
255}
256
257} // namespace WebCore
258
259#endif // ENABLE(GRAPHICS_CONTEXT_3D)
260