Replace use of OwnArrayPtr<Foo> with std::unique_ptr<Foo[]> in WebCore
[WebKit-https.git] / Source / WebCore / platform / graphics / ANGLEWebKitBridge.cpp
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 #if USE(3D_GRAPHICS)
29
30 #include "ANGLEWebKitBridge.h"
31 #include <wtf/StdLibExtras.h>
32
33 namespace WebCore {
34
35 // Temporary typedef to support an incompatible change in the ANGLE API.
36 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
37 typedef int ANGLEGetInfoType;
38 #else
39 typedef size_t ANGLEGetInfoType;
40 #endif
41
42 inline static ANGLEGetInfoType getValidationResultValue(const ShHandle compiler, ShShaderInfo shaderInfo)
43 {
44     ANGLEGetInfoType value = 0;
45     ShGetInfo(compiler, shaderInfo, &value);
46     return value;
47 }
48
49 static bool getSymbolInfo(ShHandle compiler, ShShaderInfo symbolType, Vector<ANGLEShaderSymbol>& symbols)
50 {
51     ShShaderInfo symbolMaxNameLengthType;
52
53     switch (symbolType) {
54     case SH_ACTIVE_ATTRIBUTES:
55         symbolMaxNameLengthType = SH_ACTIVE_ATTRIBUTE_MAX_LENGTH;
56         break;
57     case SH_ACTIVE_UNIFORMS:
58         symbolMaxNameLengthType = SH_ACTIVE_UNIFORM_MAX_LENGTH;
59         break;
60     default:
61         ASSERT_NOT_REACHED();
62         return false;
63     }
64
65     ANGLEGetInfoType numSymbols = getValidationResultValue(compiler, symbolType);
66
67     ANGLEGetInfoType maxNameLength = getValidationResultValue(compiler, symbolMaxNameLengthType);
68     if (maxNameLength <= 1)
69         return false;
70
71     ANGLEGetInfoType maxMappedNameLength = getValidationResultValue(compiler, SH_MAPPED_NAME_MAX_LENGTH);
72     if (maxMappedNameLength <= 1)
73         return false;
74
75     // The maximum allowed symbol name length is 256 characters.
76     Vector<char, 256> nameBuffer(maxNameLength);
77     Vector<char, 256> mappedNameBuffer(maxMappedNameLength);
78     
79     for (ANGLEGetInfoType i = 0; i < numSymbols; ++i) {
80         ANGLEShaderSymbol symbol;
81         ANGLEGetInfoType nameLength = 0;
82         switch (symbolType) {
83         case SH_ACTIVE_ATTRIBUTES:
84             symbol.symbolType = SHADER_SYMBOL_TYPE_ATTRIBUTE;
85             ShGetActiveAttrib(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.data(), mappedNameBuffer.data());
86             break;
87         case SH_ACTIVE_UNIFORMS:
88             symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM;
89             ShGetActiveUniform(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.data(), mappedNameBuffer.data());
90             break;
91         default:
92             ASSERT_NOT_REACHED();
93             return false;
94         }
95         if (!nameLength)
96             return false;
97         
98         // The ShGetActive* calls above are guaranteed to produce null-terminated strings for
99         // nameBuffer and mappedNameBuffer. Also, the character set for symbol names
100         // is a subset of Latin-1 as specified by the OpenGL ES Shading Language, Section 3.1 and
101         // WebGL, Section "Characters Outside the GLSL Source Character Set".
102
103         String name = String(nameBuffer.data());
104         String mappedName = String(mappedNameBuffer.data());
105         
106         // ANGLE returns array names in the format "array[0]".
107         // The only way to know if a symbol is an array is to check if it ends with "[0]".
108         // We can't check the size because regular symbols and arrays of length 1 both have a size of 1.
109         symbol.isArray = name.endsWith("[0]") && mappedName.endsWith("[0]");
110         if (symbol.isArray) {
111             // Add a symbol for the array name without the "[0]" suffix.
112             name.truncate(name.length() - 3);
113             mappedName.truncate(mappedName.length() - 3);
114         }
115
116         symbol.name = name;
117         symbol.mappedName = mappedName;
118         symbols.append(symbol);
119     
120         if (symbol.isArray) {
121             // Add symbols for each array element.
122             symbol.isArray = false;
123             for (int i = 0; i < symbol.size; i++) {
124                 String arrayBrackets = "[" + String::number(i) + "]";
125                 symbol.name = name + arrayBrackets;
126                 symbol.mappedName = mappedName + arrayBrackets;
127                 symbols.append(symbol);
128             }
129         }
130     }
131     return true;
132 }
133
134 ANGLEWebKitBridge::ANGLEWebKitBridge(ShShaderOutput shaderOutput, ShShaderSpec shaderSpec)
135     : builtCompilers(false)
136     , m_fragmentCompiler(0)
137     , m_vertexCompiler(0)
138     , m_shaderOutput(shaderOutput)
139     , m_shaderSpec(shaderSpec)
140 {
141     // This is a no-op if it's already initialized.
142     ShInitialize();
143 }
144
145 ANGLEWebKitBridge::~ANGLEWebKitBridge()
146 {
147     cleanupCompilers();
148 }
149
150 void ANGLEWebKitBridge::cleanupCompilers()
151 {
152     if (m_fragmentCompiler)
153         ShDestruct(m_fragmentCompiler);
154     m_fragmentCompiler = 0;
155     if (m_vertexCompiler)
156         ShDestruct(m_vertexCompiler);
157     m_vertexCompiler = 0;
158
159     builtCompilers = false;
160 }
161     
162 void ANGLEWebKitBridge::setResources(ShBuiltInResources resources)
163 {
164     // Resources are (possibly) changing - cleanup compilers if we had them already
165     cleanupCompilers();
166     
167     m_resources = resources;
168 }
169
170 bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions)
171 {
172     if (!builtCompilers) {
173         m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
174         m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
175         if (!m_fragmentCompiler || !m_vertexCompiler) {
176             cleanupCompilers();
177             return false;
178         }
179
180         builtCompilers = true;
181     }
182     
183     ShHandle compiler;
184
185     if (shaderType == SHADER_TYPE_VERTEX)
186         compiler = m_vertexCompiler;
187     else
188         compiler = m_fragmentCompiler;
189
190     const char* const shaderSourceStrings[] = { shaderSource };
191
192     bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions);
193     if (!validateSuccess) {
194         int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH);
195         if (logSize > 1) {
196             auto logBuffer = std::make_unique<char[]>(logSize);
197             if (logBuffer) {
198                 ShGetInfoLog(compiler, logBuffer.get());
199                 shaderValidationLog = logBuffer.get();
200             }
201         }
202         return false;
203     }
204
205     int translationLength = getValidationResultValue(compiler, SH_OBJECT_CODE_LENGTH);
206     if (translationLength > 1) {
207         auto translationBuffer = std::make_unique<char[]>(translationLength);
208         if (!translationBuffer)
209             return false;
210         ShGetObjectCode(compiler, translationBuffer.get());
211         translatedShaderSource = translationBuffer.get();
212     }
213     
214     if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols))
215         return false;
216     if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols))
217         return false;
218
219     return true;
220 }
221
222 }
223
224 #endif // USE(3D_GRAPHICS)