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 | |
64 | namespace WebCore { |
65 | |
66 | Extensions3DOpenGLCommon::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 | |
99 | Extensions3DOpenGLCommon::~Extensions3DOpenGLCommon() = default; |
100 | |
101 | bool 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 | |
115 | void 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 | |
153 | bool 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 | |
162 | int Extensions3DOpenGLCommon::getGraphicsResetStatusARB() |
163 | { |
164 | return GraphicsContext3D::NO_ERROR; |
165 | } |
166 | |
167 | String 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 = 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 | |
215 | void 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 | |
242 | void Extensions3DOpenGLCommon::readnPixelsEXT(int, int, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, GC3Dsizei, void *) |
243 | { |
244 | m_context->synthesizeGLError(GL_INVALID_OPERATION); |
245 | } |
246 | |
247 | void Extensions3DOpenGLCommon::getnUniformfvEXT(GC3Duint, int, GC3Dsizei, float *) |
248 | { |
249 | m_context->synthesizeGLError(GL_INVALID_OPERATION); |
250 | } |
251 | |
252 | void 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 | |