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