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 USE(3D_GRAPHICS)
30#include "Extensions3DOpenGLCommon.h"
31
32#include "ANGLEWebKitBridge.h"
33#include "GraphicsContext3D.h"
34
35#if PLATFORM(IOS)
36#include <OpenGLES/ES2/glext.h>
37#else
38#if USE(OPENGL_ES_2)
39#include "OpenGLESShims.h"
40#include <GLES2/gl2.h>
41#include <GLES2/gl2ext.h>
42#elif PLATFORM(MAC)
43#include <OpenGL/gl.h>
44#elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)
45#include "OpenGLShims.h"
46#endif
47#endif
48
49#include <wtf/MainThread.h>
50#include <wtf/Vector.h>
51
52namespace WebCore {
53
54Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context)
55    : m_initializedAvailableExtensions(false)
56    , m_context(context)
57    , m_isNVIDIA(false)
58    , m_isAMD(false)
59    , m_isIntel(false)
60    , m_isImagination(false)
61    , m_maySupportMultisampling(true)
62    , m_requiresBuiltInFunctionEmulation(false)
63    , m_requiresRestrictedMaximumTextureSize(false)
64{
65    m_vendor = String(reinterpret_cast<const char*>(::glGetString(GL_VENDOR)));
66    m_renderer = String(reinterpret_cast<const char*>(::glGetString(GL_RENDERER)));
67
68    Vector<String> vendorComponents;
69    m_vendor.lower().split(' ', vendorComponents);
70    if (vendorComponents.contains("nvidia"))
71        m_isNVIDIA = true;
72    if (vendorComponents.contains("ati") || vendorComponents.contains("amd"))
73        m_isAMD = true;
74    if (vendorComponents.contains("intel"))
75        m_isIntel = true;
76    if (vendorComponents.contains("imagination"))
77        m_isImagination = true;
78
79#if PLATFORM(MAC)
80    if (m_isAMD || m_isIntel)
81        m_requiresBuiltInFunctionEmulation = true;
82
83    // Currently in Mac we only allow multisampling if the vendor is NVIDIA,
84    // or if the vendor is AMD/ATI and the system is 10.7.2 and above.
85
86    bool systemSupportsMultisampling = true;
87#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1080
88    ASSERT(isMainThread());
89    static SInt32 version;
90    if (!version) {
91        if (Gestalt(gestaltSystemVersion, &version) != noErr)
92            systemSupportsMultisampling = false;
93    }
94    // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details
95    if (systemSupportsMultisampling)
96        systemSupportsMultisampling = version >= 0x1072;
97#endif // SNOW_LEOPARD and LION
98
99    if (m_isAMD && !systemSupportsMultisampling)
100        m_maySupportMultisampling = false;
101
102    // Intel HD 3000 devices have problems with large textures. <rdar://problem/16649140>
103    if (m_isIntel)
104        m_requiresRestrictedMaximumTextureSize = m_renderer.startsWith("Intel HD Graphics 3000");
105#endif
106}
107
108Extensions3DOpenGLCommon::~Extensions3DOpenGLCommon()
109{
110}
111
112bool Extensions3DOpenGLCommon::supports(const String& name)
113{
114    if (!m_initializedAvailableExtensions)
115        initializeAvailableExtensions();
116
117    return supportsExtension(name);
118}
119
120void Extensions3DOpenGLCommon::ensureEnabled(const String& name)
121{
122    if (name == "GL_OES_standard_derivatives") {
123        // Enable support in ANGLE (if not enabled already)
124        ANGLEWebKitBridge& compiler = m_context->m_compiler;
125        ShBuiltInResources ANGLEResources = compiler.getResources();
126        if (!ANGLEResources.OES_standard_derivatives) {
127            ANGLEResources.OES_standard_derivatives = 1;
128            compiler.setResources(ANGLEResources);
129        }
130    } else if (name == "GL_EXT_draw_buffers") {
131        // Enable support in ANGLE (if not enabled already)
132        ANGLEWebKitBridge& compiler = m_context->m_compiler;
133        ShBuiltInResources ANGLEResources = compiler.getResources();
134        if (!ANGLEResources.EXT_draw_buffers) {
135            ANGLEResources.EXT_draw_buffers = 1;
136            m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &ANGLEResources.MaxDrawBuffers);
137            compiler.setResources(ANGLEResources);
138        }
139    } else if (name == "GL_EXT_shader_texture_lod") {
140        // Enable support in ANGLE (if not enabled already)
141        ANGLEWebKitBridge& compiler = m_context->m_compiler;
142        ShBuiltInResources ANGLEResources = compiler.getResources();
143        if (!ANGLEResources.EXT_shader_texture_lod) {
144            ANGLEResources.EXT_shader_texture_lod = 1;
145            compiler.setResources(ANGLEResources);
146        }
147    }
148}
149
150bool Extensions3DOpenGLCommon::isEnabled(const String& name)
151{
152    if (name == "GL_OES_standard_derivatives") {
153        ANGLEWebKitBridge& compiler = m_context->m_compiler;
154        return compiler.getResources().OES_standard_derivatives;
155    }
156    return supports(name);
157}
158
159int Extensions3DOpenGLCommon::getGraphicsResetStatusARB()
160{
161    return GraphicsContext3D::NO_ERROR;
162}
163
164String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject shader)
165{
166    ASSERT(shader);
167    int GLshaderType;
168    ANGLEShaderType shaderType;
169
170    ANGLEWebKitBridge& compiler = m_context->m_compiler;
171
172    m_context->getShaderiv(shader, GraphicsContext3D::SHADER_TYPE, &GLshaderType);
173
174    if (GLshaderType == GraphicsContext3D::VERTEX_SHADER)
175        shaderType = SHADER_TYPE_VERTEX;
176    else if (GLshaderType == GraphicsContext3D::FRAGMENT_SHADER)
177        shaderType = SHADER_TYPE_FRAGMENT;
178    else
179        return ""; // Invalid shader type.
180
181    HashMap<Platform3DObject, GraphicsContext3D::ShaderSourceEntry>::iterator result = m_context->m_shaderSourceMap.find(shader);
182
183    if (result == m_context->m_shaderSourceMap.end())
184        return "";
185
186    GraphicsContext3D::ShaderSourceEntry& entry = result->value;
187
188    String translatedShaderSource;
189    String shaderInfoLog;
190    int extraCompileOptions = SH_CLAMP_INDIRECT_ARRAY_BOUNDS | SH_UNFOLD_SHORT_CIRCUIT | SH_ENFORCE_PACKING_RESTRICTIONS | SH_INIT_VARYINGS_WITHOUT_STATIC_USE | SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH;
191
192    if (m_requiresBuiltInFunctionEmulation)
193        extraCompileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
194
195    Vector<ANGLEShaderSymbol> symbols;
196    bool isValid = compiler.compileShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, symbols, extraCompileOptions);
197
198    entry.log = shaderInfoLog;
199    entry.isValid = isValid;
200
201    size_t numSymbols = symbols.size();
202    for (size_t i = 0; i < numSymbols; ++i) {
203        ANGLEShaderSymbol shaderSymbol = symbols[i];
204        GraphicsContext3D::SymbolInfo symbolInfo(shaderSymbol.dataType, shaderSymbol.size, shaderSymbol.mappedName, shaderSymbol.precision, shaderSymbol.staticUse);
205        entry.symbolMap(shaderSymbol.symbolType).set(shaderSymbol.name, symbolInfo);
206    }
207
208    if (!isValid)
209        return "";
210
211    return translatedShaderSource;
212}
213
214void Extensions3DOpenGLCommon::initializeAvailableExtensions()
215{
216    String extensionsString = getExtensions();
217    Vector<String> availableExtensions;
218    extensionsString.split(" ", availableExtensions);
219    for (size_t i = 0; i < availableExtensions.size(); ++i)
220        m_availableExtensions.add(availableExtensions[i]);
221    m_initializedAvailableExtensions = true;
222}
223
224void Extensions3DOpenGLCommon::readnPixelsEXT(int, int, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, GC3Dsizei, void *)
225{
226    m_context->synthesizeGLError(GL_INVALID_OPERATION);
227}
228
229void Extensions3DOpenGLCommon::getnUniformfvEXT(GC3Duint, int, GC3Dsizei, float *)
230{
231    m_context->synthesizeGLError(GL_INVALID_OPERATION);
232}
233
234void Extensions3DOpenGLCommon::getnUniformivEXT(GC3Duint, int, GC3Dsizei, int *)
235{
236    m_context->synthesizeGLError(GL_INVALID_OPERATION);
237}
238
239} // namespace WebCore
240
241#endif // USE(3D_GRAPHICS)
242