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
ReadFileToString(const std::string & source)13 static std::string ReadFileToString(const std::string &source)
14 {
15 std::ifstream stream(source);
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(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
CompileShader(GLenum type,const std::string & source)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, NULL);
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 std::vector<GLchar> infoLog(infoLogLength);
50 glGetShaderInfoLog(shader, infoLog.size(), NULL, infoLog.data());
51
52 std::cerr << "shader compilation failed: " << infoLog.data();
53
54 glDeleteShader(shader);
55 shader = 0;
56 }
57
58 return shader;
59 }
60
CompileShaderFromFile(GLenum type,const std::string & sourcePath)61 GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
62 {
63 std::string source = ReadFileToString(sourcePath);
64 if (source.empty())
65 {
66 return 0;
67 }
68
69 return CompileShader(type, source);
70 }
71
CompileProgram(const std::string & vsSource,const std::string & fsSource)72 GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
73 {
74 GLuint program = glCreateProgram();
75
76 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
77 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
78
79 if (vs == 0 || fs == 0)
80 {
81 glDeleteShader(fs);
82 glDeleteShader(vs);
83 glDeleteProgram(program);
84 return 0;
85 }
86
87 glAttachShader(program, vs);
88 glDeleteShader(vs);
89
90 glAttachShader(program, fs);
91 glDeleteShader(fs);
92
93 glLinkProgram(program);
94
95 GLint linkStatus;
96 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
97
98 if (linkStatus == 0)
99 {
100 GLint infoLogLength;
101 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
102
103 std::vector<GLchar> infoLog(infoLogLength);
104 glGetProgramInfoLog(program, infoLog.size(), NULL, infoLog.data());
105
106 std::cerr << "program link failed: " << infoLog.data();
107
108 glDeleteProgram(program);
109 return 0;
110 }
111
112 return program;
113 }
114
CompileProgramFromFiles(const std::string & vsPath,const std::string & fsPath)115 GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
116 {
117 std::string vsSource = ReadFileToString(vsPath);
118 std::string fsSource = ReadFileToString(fsPath);
119 if (vsSource.empty() || fsSource.empty())
120 {
121 return 0;
122 }
123
124 return CompileProgram(vsSource, fsSource);
125 }
126