]> git.tdb.fi Git - libs/gl.git/blob - source/program.cpp
Get rid of the typedefs for fundamental types
[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 {
24         init();
25 }
26
27 Program::Program(const string &vert, const string &frag):
28         del_shaders(true)
29 {
30         init();
31
32         attach_shader(*new Shader(VERTEX_SHADER, vert));
33         attach_shader(*new Shader(FRAGMENT_SHADER, frag));
34         link();
35 }
36
37 void Program::init()
38 {
39         static RequireExtension _ext("GL_ARB_shader_objects");
40
41         linked=false;
42         id=glCreateProgramObjectARB();
43 }
44
45 Program::~Program()
46 {
47         if(del_shaders)
48         {
49                 for(list<Shader *>::iterator i=shaders.begin(); i!=shaders.end(); ++i)
50                         delete *i;
51         }
52         glDeleteObjectARB(id);
53 }
54
55 void Program::attach_shader(Shader &shader)
56 {
57         if(find(shaders.begin(), shaders.end(), &shader)==shaders.end())
58         {
59                 glAttachObjectARB(id, shader.get_id());
60                 shaders.push_back(&shader);
61         }
62 }
63
64 void Program::detach_shader(Shader &shader)
65 {
66         list<Shader *>::iterator i=remove(shaders.begin(), shaders.end(), &shader);
67         if(i!=shaders.end())
68         {
69                 shaders.erase(i, shaders.end());
70                 glDetachObjectARB(id, shader.get_id());
71         }
72 }
73
74 void Program::set_del_shaders(bool ds)
75 {
76         del_shaders=ds;
77 }
78
79 void Program::bind_attribute(unsigned index, const string &name)
80 {
81         static RequireExtension _ext("GL_ARB_vertex_shader");
82         glBindAttribLocationARB(id, index, name.c_str());
83 }
84
85 void Program::link()
86 {
87         for(list<Shader *>::iterator i=shaders.begin(); i!=shaders.end(); ++i)
88                 if(!(*i)->get_compiled())
89                         (*i)->compile();
90
91         glLinkProgramARB(id);
92         if(!(linked=get_param(GL_LINK_STATUS)))
93                 throw CompileError(get_info_log());
94 }
95
96 int Program::get_param(GLenum param) const
97 {
98         int value;
99         glGetObjectParameterivARB(id, param, &value);
100         return value;
101 }
102
103 string Program::get_info_log() const
104 {
105         GLsizei len=get_param(GL_INFO_LOG_LENGTH);
106         char log[len+1];
107         glGetInfoLogARB(id, len+1, &len, log);
108         return string(log, len);
109 }
110
111 void Program::bind() const
112 {
113         if(!linked)
114                 throw InvalidState("Program is not linked");
115
116         glUseProgramObjectARB(id);
117         cur_prog=this;
118 }
119
120 int Program::get_uniform_location(const string &n) const
121 {
122         return glGetUniformLocationARB(id, n.c_str());
123 }
124
125 void Program::unbind()
126 {
127         if(cur_prog)
128         {
129                 glUseProgramObjectARB(0);
130                 cur_prog=0;
131         }
132 }
133
134 void Program::maybe_bind()
135 {
136         if(cur_prog!=this)
137                 bind();
138 }
139
140 const Program *Program::cur_prog=0;
141
142
143 Program::Loader::Loader(Program &p):
144         DataFile::ObjectLoader<Program>(p)
145 {
146         obj.set_del_shaders(true);
147
148         add("vertex_shader",   &Loader::vertex_shader);
149         add("fragment_shader", &Loader::fragment_shader);
150         add("attribute",       &Loader::attribute);
151 }
152
153 void Program::Loader::vertex_shader(const string &src)
154 {
155         obj.attach_shader(*new Shader(VERTEX_SHADER, src));
156 }
157
158 void Program::Loader::fragment_shader(const string &src)
159 {
160         obj.attach_shader(*new Shader(FRAGMENT_SHADER, src));
161 }
162
163 void Program::Loader::attribute(unsigned i, const string &n)
164 {
165         obj.bind_attribute(i, n);
166 }
167
168 void Program::Loader::finish()
169 {
170         obj.link();
171 }
172
173 } // namespace GL
174 } // namespace Msp