Upload upstream chromium 67.0.3396
[platform/framework/web/chromium-efl.git] / third_party / angle / util / shader_utils.cpp
1 //
2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "shader_utils.h"
8
9 #include <vector>
10 #include <iostream>
11 #include <fstream>
12
13 static std::string ReadFileToString(const std::string &source)
14 {
15     std::ifstream stream(source.c_str());
16     if (!stream)
17     {
18         std::cerr << "Failed to load shader file: " << source;
19         return "";
20     }
21
22     std::string result;
23
24     stream.seekg(0, std::ios::end);
25     result.reserve(static_cast<unsigned int>(stream.tellg()));
26     stream.seekg(0, std::ios::beg);
27
28     result.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
29
30     return result;
31 }
32
33 GLuint CompileShader(GLenum type, const std::string &source)
34 {
35     GLuint shader = glCreateShader(type);
36
37     const char *sourceArray[1] = { source.c_str() };
38     glShaderSource(shader, 1, sourceArray, nullptr);
39     glCompileShader(shader);
40
41     GLint compileResult;
42     glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
43
44     if (compileResult == 0)
45     {
46         GLint infoLogLength;
47         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
48
49         // Info log length includes the null terminator, so 1 means that the info log is an empty
50         // string.
51         if (infoLogLength > 1)
52         {
53             std::vector<GLchar> infoLog(infoLogLength);
54             glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
55             std::cerr << "shader compilation failed: " << &infoLog[0];
56         }
57         else
58         {
59             std::cerr << "shader compilation failed. <Empty log message>";
60         }
61
62         std::cerr << std::endl;
63
64         glDeleteShader(shader);
65         shader = 0;
66     }
67
68     return shader;
69 }
70
71 GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
72 {
73     std::string source = ReadFileToString(sourcePath);
74     if (source.empty())
75     {
76         return 0;
77     }
78
79     return CompileShader(type, source);
80 }
81
82 GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
83 {
84     if (glGetError() != GL_NO_ERROR)
85         return 0;
86
87     GLint linkStatus;
88     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
89     if (linkStatus == 0)
90     {
91         if (outputErrorMessages)
92         {
93             GLint infoLogLength;
94             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
95
96             // Info log length includes the null terminator, so 1 means that the info log is an
97             // empty string.
98             if (infoLogLength > 1)
99             {
100                 std::vector<GLchar> infoLog(infoLogLength);
101                 glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
102                                     &infoLog[0]);
103
104                 std::cerr << "program link failed: " << &infoLog[0];
105             }
106             else
107             {
108                 std::cerr << "program link failed. <Empty log message>";
109             }
110         }
111
112         glDeleteProgram(program);
113         return 0;
114     }
115
116     return program;
117 }
118
119 GLuint CompileProgramWithTransformFeedback(
120     const std::string &vsSource,
121     const std::string &fsSource,
122     const std::vector<std::string> &transformFeedbackVaryings,
123     GLenum bufferMode)
124 {
125     return CompileProgramWithGSAndTransformFeedback(vsSource, "", fsSource,
126                                                     transformFeedbackVaryings, bufferMode);
127 }
128
129 GLuint CompileProgramWithGSAndTransformFeedback(
130     const std::string &vsSource,
131     const std::string &gsSource,
132     const std::string &fsSource,
133     const std::vector<std::string> &transformFeedbackVaryings,
134     GLenum bufferMode)
135 {
136     GLuint program = glCreateProgram();
137
138     GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
139     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
140
141     if (vs == 0 || fs == 0)
142     {
143         glDeleteShader(fs);
144         glDeleteShader(vs);
145         glDeleteProgram(program);
146         return 0;
147     }
148
149     glAttachShader(program, vs);
150     glDeleteShader(vs);
151
152     glAttachShader(program, fs);
153     glDeleteShader(fs);
154
155     if (!gsSource.empty())
156     {
157         GLuint gs = CompileShader(GL_GEOMETRY_SHADER_EXT, gsSource);
158         if (gs == 0)
159         {
160             glDeleteShader(vs);
161             glDeleteShader(fs);
162             glDeleteProgram(program);
163             return 0;
164         }
165
166         glAttachShader(program, gs);
167         glDeleteShader(gs);
168     }
169
170     if (transformFeedbackVaryings.size() > 0)
171     {
172         std::vector<const char *> constCharTFVaryings;
173
174         for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
175         {
176             constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
177         }
178
179         glTransformFeedbackVaryings(program, static_cast<GLsizei>(transformFeedbackVaryings.size()),
180                                     &constCharTFVaryings[0], bufferMode);
181     }
182
183     glLinkProgram(program);
184
185     return CheckLinkStatusAndReturnProgram(program, true);
186 }
187
188 GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
189 {
190     return CompileProgramWithGS(vsSource, "", fsSource);
191 }
192
193 GLuint CompileProgramWithGS(const std::string &vsSource,
194                             const std::string &gsSource,
195                             const std::string &fsSource)
196 {
197     std::vector<std::string> emptyVector;
198     return CompileProgramWithGSAndTransformFeedback(vsSource, gsSource, fsSource, emptyVector,
199                                                     GL_NONE);
200 }
201
202 GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
203 {
204     std::string vsSource = ReadFileToString(vsPath);
205     std::string fsSource = ReadFileToString(fsPath);
206     if (vsSource.empty() || fsSource.empty())
207     {
208         return 0;
209     }
210
211     return CompileProgram(vsSource, fsSource);
212 }
213
214 GLuint CompileComputeProgram(const std::string &csSource, bool outputErrorMessages)
215 {
216     GLuint program = glCreateProgram();
217
218     GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
219     if (cs == 0)
220     {
221         glDeleteProgram(program);
222         return 0;
223     }
224
225     glAttachShader(program, cs);
226
227     glLinkProgram(program);
228
229     return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
230 }
231
232 GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
233 {
234     GLuint program = glCreateProgram();
235     glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
236     return CheckLinkStatusAndReturnProgram(program, true);
237 }
238
239 GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
240 {
241     GLuint program = glCreateProgram();
242     glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
243     return CheckLinkStatusAndReturnProgram(program, true);
244 }
245
246 bool LinkAttachedProgram(GLuint program)
247 {
248     glLinkProgram(program);
249     return (CheckLinkStatusAndReturnProgram(program, true) != 0);
250 }