]> git.tdb.fi Git - libs/gl.git/blob - source/program.cpp
Add a missing #include
[libs/gl.git] / source / program.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <algorithm>
9 #include "arb_shader_objects.h"
10 #include "arb_vertex_shader.h"
11 #include "except.h"
12 #include "extension.h"
13 #include "program.h"
14 #include "shader.h"
15
16 using namespace std;
17
18 namespace Msp {
19 namespace GL {
20
21 Program::Program():
22         del_shaders(false),
23         linked(false)
24 {
25         require_extension("GL_ARB_shader_objects");
26         require_extension("GL_ARB_vertex_shader");
27
28         id=glCreateProgramObjectARB();
29 }
30
31 Program::Program(const string &vert, const string &frag):
32         del_shaders(true),
33         linked(false)
34 {
35         require_extension("GL_ARB_shader_objects");
36         require_extension("GL_ARB_vertex_shader");
37
38         id=glCreateProgramObjectARB();
39         attach_shader(*new Shader(VERTEX_SHADER, vert));
40         attach_shader(*new Shader(FRAGMENT_SHADER, frag));
41         link();
42 }
43
44 Program::~Program()
45 {
46         if(del_shaders)
47         {
48                 for(list<Shader *>::iterator i=shaders.begin(); i!=shaders.end(); ++i)
49                         delete *i;
50         }
51         glDeleteObjectARB(id);
52 }
53
54 void Program::attach_shader(Shader &shader)
55 {
56         if(find(shaders.begin(), shaders.end(), &shader)==shaders.end())
57         {
58                 glAttachObjectARB(id, shader.get_id());
59                 shaders.push_back(&shader);
60         }
61 }
62
63 void Program::detach_shader(Shader &shader)
64 {
65         list<Shader *>::iterator i=remove(shaders.begin(), shaders.end(), &shader);
66         if(i!=shaders.end())
67         {
68                 shaders.erase(i, shaders.end());
69                 glDetachObjectARB(id, shader.get_id());
70         }
71 }
72
73 void Program::set_del_shaders(bool ds)
74 {
75         del_shaders=ds;
76 }
77
78 void Program::bind_attribute(uint index, const string &name)
79 {
80         glBindAttribLocationARB(id, index, name.c_str());
81 }
82
83 void Program::link()
84 {
85         for(list<Shader *>::iterator i=shaders.begin(); i!=shaders.end(); ++i)
86                 if(!(*i)->get_compiled())
87                         (*i)->compile();
88
89         glLinkProgramARB(id);
90         if(!(linked=get_param(GL_LINK_STATUS)))
91                 throw CompileError(get_info_log());
92 }
93
94 int Program::get_param(GLenum param) const
95 {
96         int value;
97         glGetObjectParameterivARB(id, param, &value);
98         return value;
99 }
100
101 string Program::get_info_log() const
102 {
103         sizei len=get_param(GL_INFO_LOG_LENGTH);
104         char log[len+1];
105         glGetInfoLogARB(id, len+1, reinterpret_cast<GLsizei *>(&len), log);
106         return string(log, len);
107 }
108
109 void Program::bind()
110 {
111         if(!linked)
112                 throw InvalidState("Program is not linked");
113
114         glUseProgramObjectARB(id);
115         cur_prog=this;
116 }
117
118 int Program::get_uniform_location(const string &n) const
119 {
120         return glGetUniformLocationARB(id, n.c_str());
121 }
122
123 /*void Program::uniform(int i, int v)
124 {
125         glUniform1iARB(i, v);
126 }
127
128 void Program::uniform(int i, float x)
129 {
130         glUniform1fARB(i, x);
131 }
132
133 void Program::uniform(int i, float x, float y)
134 {
135         glUniform2fARB(i, x, y);
136 }
137
138 void Program::uniform(int i, float x, float y, float z)
139 {
140         glUniform3fARB(i, x, y, z);
141 }
142
143 void Program::uniform(int i, float x, float y, float z, float w)
144 {
145         glUniform4fARB(i, x, y, z, w);
146 }
147
148 void Program::uniform4(int i, const float *v)
149 {
150         glUniform4fvARB(i, 1, v);
151 }
152
153 void Program::uniform_matrix4(int i, const float *v)
154 {
155         glUniformMatrix4fvARB(i, 1, false, v);
156 }*/
157
158 void Program::unbind()
159 {
160         if(cur_prog)
161         {
162                 glUseProgramObjectARB(0);
163                 cur_prog=0;
164         }
165 }
166
167 void Program::maybe_bind()
168 {
169         if(cur_prog!=this)
170                 bind();
171 }
172
173 Program *Program::cur_prog=0;
174
175
176 Program::Loader::Loader(Program &p):
177         prog(p)
178 {
179         prog.set_del_shaders(true);
180
181         add("vertex_shader",   &Loader::vertex_shader);
182         add("fragment_shader", &Loader::fragment_shader);
183         add("attribute",       &Loader::attribute);
184 }
185
186 void Program::Loader::vertex_shader(const string &src)
187 {
188         prog.attach_shader(*new Shader(VERTEX_SHADER, src));
189 }
190
191 void Program::Loader::fragment_shader(const string &src)
192 {
193         prog.attach_shader(*new Shader(FRAGMENT_SHADER, src));
194 }
195
196 void Program::Loader::attribute(uint i, const string &n)
197 {
198         prog.bind_attribute(i, n);
199 }
200
201 void Program::Loader::finish()
202 {
203         prog.link();
204 }
205
206 } // namespace GL
207 } // namespace Msp