2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "ANGLEWebKitBridge.h"
32 #include <wtf/StdLibExtras.h>
36 // Temporary typedef to support an incompatible change in the ANGLE API.
37 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
38 typedef int ANGLEGetInfoType;
40 typedef size_t ANGLEGetInfoType;
43 inline static ANGLEGetInfoType getValidationResultValue(const ShHandle compiler, ShShaderInfo shaderInfo)
45 ANGLEGetInfoType value = 0;
46 ShGetInfo(compiler, shaderInfo, &value);
50 static bool getSymbolInfo(ShHandle compiler, ShShaderInfo symbolType, Vector<ANGLEShaderSymbol>& symbols)
52 ShShaderInfo symbolMaxNameLengthType;
55 case SH_ACTIVE_ATTRIBUTES:
56 symbolMaxNameLengthType = SH_ACTIVE_ATTRIBUTE_MAX_LENGTH;
58 case SH_ACTIVE_UNIFORMS:
59 symbolMaxNameLengthType = SH_ACTIVE_UNIFORM_MAX_LENGTH;
66 ANGLEGetInfoType numSymbols = getValidationResultValue(compiler, symbolType);
68 ANGLEGetInfoType maxNameLength = getValidationResultValue(compiler, symbolMaxNameLengthType);
69 if (maxNameLength <= 1)
72 ANGLEGetInfoType maxMappedNameLength = getValidationResultValue(compiler, SH_MAPPED_NAME_MAX_LENGTH);
73 if (maxMappedNameLength <= 1)
76 // The maximum allowed symbol name length is 256 characters.
77 Vector<char, 256> nameBuffer(maxNameLength);
78 Vector<char, 256> mappedNameBuffer(maxMappedNameLength);
80 for (ANGLEGetInfoType i = 0; i < numSymbols; ++i) {
81 ANGLEShaderSymbol symbol;
82 ANGLEGetInfoType nameLength = 0;
83 ShPrecisionType precision;
86 case SH_ACTIVE_ATTRIBUTES:
87 symbol.symbolType = SHADER_SYMBOL_TYPE_ATTRIBUTE;
88 ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &precision, &staticUse, nameBuffer.data(), mappedNameBuffer.data());
90 case SH_ACTIVE_UNIFORMS:
91 symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM;
92 ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &precision, &staticUse, nameBuffer.data(), mappedNameBuffer.data());
101 // The ShGetActive* calls above are guaranteed to produce null-terminated strings for
102 // nameBuffer and mappedNameBuffer. Also, the character set for symbol names
103 // is a subset of Latin-1 as specified by the OpenGL ES Shading Language, Section 3.1 and
104 // WebGL, Section "Characters Outside the GLSL Source Character Set".
106 String name = String(nameBuffer.data());
107 String mappedName = String(mappedNameBuffer.data());
108 LOG(WebGL, "Map shader symbol %s -> %s\n", name.utf8().data(), mappedName.utf8().data());
110 // ANGLE returns array names in the format "array[0]".
111 // The only way to know if a symbol is an array is to check if it ends with "[0]".
112 // We can't check the size because regular symbols and arrays of length 1 both have a size of 1.
113 symbol.isArray = name.endsWith("[0]") && mappedName.endsWith("[0]");
114 if (symbol.isArray) {
115 // Add a symbol for the array name without the "[0]" suffix.
116 name.truncate(name.length() - 3);
117 mappedName.truncate(mappedName.length() - 3);
121 symbol.mappedName = mappedName;
122 symbols.append(symbol);
124 if (symbol.isArray) {
125 // Add symbols for each array element.
126 symbol.isArray = false;
127 for (int i = 0; i < symbol.size; i++) {
128 String arrayBrackets = "[" + String::number(i) + "]";
129 symbol.name = name + arrayBrackets;
130 symbol.mappedName = mappedName + arrayBrackets;
131 symbols.append(symbol);
138 ANGLEWebKitBridge::ANGLEWebKitBridge(ShShaderOutput shaderOutput, ShShaderSpec shaderSpec)
139 : builtCompilers(false)
140 , m_fragmentCompiler(0)
141 , m_vertexCompiler(0)
142 , m_shaderOutput(shaderOutput)
143 , m_shaderSpec(shaderSpec)
145 // This is a no-op if it's already initialized.
149 ANGLEWebKitBridge::~ANGLEWebKitBridge()
154 void ANGLEWebKitBridge::cleanupCompilers()
156 if (m_fragmentCompiler)
157 ShDestruct(m_fragmentCompiler);
158 m_fragmentCompiler = 0;
159 if (m_vertexCompiler)
160 ShDestruct(m_vertexCompiler);
161 m_vertexCompiler = 0;
163 builtCompilers = false;
166 void ANGLEWebKitBridge::setResources(ShBuiltInResources resources)
168 // Resources are (possibly) changing - cleanup compilers if we had them already
171 m_resources = resources;
174 bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions)
176 if (!builtCompilers) {
177 m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
178 m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
179 if (!m_fragmentCompiler || !m_vertexCompiler) {
184 builtCompilers = true;
189 if (shaderType == SHADER_TYPE_VERTEX)
190 compiler = m_vertexCompiler;
192 compiler = m_fragmentCompiler;
194 const char* const shaderSourceStrings[] = { shaderSource };
196 bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions);
197 if (!validateSuccess) {
198 int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH);
200 auto logBuffer = std::make_unique<char[]>(logSize);
202 ShGetInfoLog(compiler, logBuffer.get());
203 shaderValidationLog = logBuffer.get();
209 int translationLength = getValidationResultValue(compiler, SH_OBJECT_CODE_LENGTH);
210 if (translationLength > 1) {
211 auto translationBuffer = std::make_unique<char[]>(translationLength);
212 if (!translationBuffer)
214 ShGetObjectCode(compiler, translationBuffer.get());
215 translatedShaderSource = translationBuffer.get();
218 if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols))
220 if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols))
228 #endif // USE(3D_GRAPHICS)