• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25 
26 #include "config.h"
27 
28 #include "platform/graphics/angle/ANGLEPlatformBridge.h"
29 
30 #include "wtf/OwnPtr.h"
31 #include "wtf/PassOwnPtr.h"
32 
33 namespace WebCore {
34 
35 typedef size_t ANGLEGetInfoType;
36 
getValidationResultValue(const ShHandle compiler,ShShaderInfo shaderInfo)37 inline static ANGLEGetInfoType getValidationResultValue(const ShHandle compiler, ShShaderInfo shaderInfo)
38 {
39     ANGLEGetInfoType value = 0;
40     ShGetInfo(compiler, shaderInfo, &value);
41     return value;
42 }
43 
getSymbolInfo(ShHandle compiler,ShShaderInfo symbolType,Vector<ANGLEShaderSymbol> & symbols)44 static bool getSymbolInfo(ShHandle compiler, ShShaderInfo symbolType, Vector<ANGLEShaderSymbol>& symbols)
45 {
46     ShShaderInfo symbolMaxNameLengthType;
47 
48     switch (symbolType) {
49     case SH_ACTIVE_ATTRIBUTES:
50         symbolMaxNameLengthType = SH_ACTIVE_ATTRIBUTE_MAX_LENGTH;
51         break;
52     case SH_ACTIVE_UNIFORMS:
53         symbolMaxNameLengthType = SH_ACTIVE_UNIFORM_MAX_LENGTH;
54         break;
55     default:
56         ASSERT_NOT_REACHED();
57         return false;
58     }
59 
60     ANGLEGetInfoType numSymbols = getValidationResultValue(compiler, symbolType);
61 
62     ANGLEGetInfoType maxNameLength = getValidationResultValue(compiler, symbolMaxNameLengthType);
63     if (maxNameLength <= 1)
64         return false;
65 
66     ANGLEGetInfoType maxMappedNameLength = getValidationResultValue(compiler, SH_MAPPED_NAME_MAX_LENGTH);
67     if (maxMappedNameLength <= 1)
68         return false;
69 
70     // The maximum allowed symbol name length is 256 characters.
71     Vector<char, 256> nameBuffer(maxNameLength);
72     Vector<char, 256> mappedNameBuffer(maxMappedNameLength);
73 
74     for (ANGLEGetInfoType i = 0; i < numSymbols; ++i) {
75         ANGLEShaderSymbol symbol;
76         ANGLEGetInfoType nameLength = 0;
77         switch (symbolType) {
78         case SH_ACTIVE_ATTRIBUTES:
79             symbol.symbolType = SHADER_SYMBOL_TYPE_ATTRIBUTE;
80 #if ANGLE_SH_VERSION >= 112
81             ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, &symbol.staticUse, nameBuffer.data(), mappedNameBuffer.data());
82 #else
83             ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, nameBuffer.data(), mappedNameBuffer.data());
84 #endif
85             break;
86         case SH_ACTIVE_UNIFORMS:
87             symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM;
88 #if ANGLE_SH_VERSION >= 112
89             ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, &symbol.staticUse, nameBuffer.data(), mappedNameBuffer.data());
90 #else
91             ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, nameBuffer.data(), mappedNameBuffer.data());
92 #endif
93             break;
94         default:
95             ASSERT_NOT_REACHED();
96             return false;
97         }
98         if (!nameLength)
99             return false;
100 
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".
105 
106         String name = String(nameBuffer.data());
107         String mappedName = String(mappedNameBuffer.data());
108 
109         // ANGLE returns array names in the format "array[0]".
110         // The only way to know if a symbol is an array is to check if it ends with "[0]".
111         // We can't check the size because regular symbols and arrays of length 1 both have a size of 1.
112         symbol.isArray = name.endsWith("[0]") && mappedName.endsWith("[0]");
113         if (symbol.isArray) {
114             // Add a symbol for the array name without the "[0]" suffix.
115             name.truncate(name.length() - 3);
116             mappedName.truncate(mappedName.length() - 3);
117         }
118 
119         symbol.name = name;
120         symbol.mappedName = mappedName;
121         symbols.append(symbol);
122 
123         if (symbol.isArray) {
124             // Add symbols for each array element.
125             symbol.isArray = false;
126             for (int i = 0; i < symbol.size; i++) {
127                 String arrayBrackets = "[" + String::number(i) + "]";
128                 symbol.name = name + arrayBrackets;
129                 symbol.mappedName = mappedName + arrayBrackets;
130                 symbols.append(symbol);
131             }
132         }
133     }
134     return true;
135 }
136 
ANGLEPlatformBridge(ShShaderOutput shaderOutput,ShShaderSpec shaderSpec)137 ANGLEPlatformBridge::ANGLEPlatformBridge(ShShaderOutput shaderOutput, ShShaderSpec shaderSpec)
138     : builtCompilers(false)
139     , m_fragmentCompiler(0)
140     , m_vertexCompiler(0)
141     , m_shaderOutput(shaderOutput)
142     , m_shaderSpec(shaderSpec)
143 {
144     // This is a no-op if it's already initialized.
145     ShInitialize();
146 }
147 
~ANGLEPlatformBridge()148 ANGLEPlatformBridge::~ANGLEPlatformBridge()
149 {
150     cleanupCompilers();
151 }
152 
cleanupCompilers()153 void ANGLEPlatformBridge::cleanupCompilers()
154 {
155     if (m_fragmentCompiler)
156         ShDestruct(m_fragmentCompiler);
157     m_fragmentCompiler = 0;
158     if (m_vertexCompiler)
159         ShDestruct(m_vertexCompiler);
160     m_vertexCompiler = 0;
161 
162     builtCompilers = false;
163 }
164 
setResources(ShBuiltInResources resources)165 void ANGLEPlatformBridge::setResources(ShBuiltInResources resources)
166 {
167     // Resources are (possibly) changing - cleanup compilers if we had them already
168     cleanupCompilers();
169 
170     m_resources = resources;
171 }
172 
compileShaderSource(const char * shaderSource,ANGLEShaderType shaderType,String & translatedShaderSource,String & shaderValidationLog,Vector<ANGLEShaderSymbol> & symbols,int extraCompileOptions)173 bool ANGLEPlatformBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions)
174 {
175     if (!builtCompilers) {
176         m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
177         m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
178         if (!m_fragmentCompiler || !m_vertexCompiler) {
179             cleanupCompilers();
180             return false;
181         }
182 
183         builtCompilers = true;
184     }
185 
186     ShHandle compiler;
187 
188     if (shaderType == SHADER_TYPE_VERTEX)
189         compiler = m_vertexCompiler;
190     else
191         compiler = m_fragmentCompiler;
192 
193     const char* const shaderSourceStrings[] = { shaderSource };
194 
195 #if ANGLE_SH_VERSION >= 111
196     bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions);
197 #else
198     bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions);
199 #endif
200     if (!validateSuccess) {
201         int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH);
202         if (logSize > 1) {
203             OwnPtr<char[]> logBuffer = adoptArrayPtr(new char[logSize]);
204             if (logBuffer) {
205                 ShGetInfoLog(compiler, logBuffer.get());
206                 shaderValidationLog = logBuffer.get();
207             }
208         }
209         return false;
210     }
211 
212     int translationLength = getValidationResultValue(compiler, SH_OBJECT_CODE_LENGTH);
213     if (translationLength > 1) {
214         OwnPtr<char[]> translationBuffer = adoptArrayPtr(new char[translationLength]);
215         if (!translationBuffer)
216             return false;
217         ShGetObjectCode(compiler, translationBuffer.get());
218         translatedShaderSource = translationBuffer.get();
219     }
220 
221     if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols))
222         return false;
223     if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols))
224         return false;
225 
226     return true;
227 }
228 
229 }
230