]> git.tdb.fi Git - libs/gl.git/blob - source/renderer.cpp
Fix an uninitialized variable
[libs/gl.git] / source / renderer.cpp
1 #include "batch.h"
2 #include "buffer.h"
3 #include "camera.h"
4 #include "error.h"
5 #include "material.h"
6 #include "program.h"
7 #include "programdata.h"
8 #include "renderer.h"
9 #include "texture.h"
10 #include "texturing.h"
11 #include "vertexarray.h"
12 #include "windingtest.h"
13
14 using namespace std;
15
16 namespace Msp {
17 namespace GL {
18
19 Renderer::Renderer(const Camera *c):
20         mtx_stack(*this),
21         mtx_changed(false),
22         camera(c),
23         state_stack(1),
24         vertex_array(0),
25         vertex_array_changed(false),
26         element_buffer(0)
27 {
28         state_stack.reserve(16);
29         shdata_stack.reserve(32);
30         state = &state_stack.back();
31
32         MatrixStack::modelview().push();
33         if(camera)
34         {
35                 MatrixStack::projection().push();
36                 camera->apply();
37                 mtx_stack.load(camera->get_matrix());
38         }
39         else
40                 mtx_stack.load(MatrixStack::modelview().top());
41 }
42
43 Renderer::~Renderer()
44 {
45         if(camera)
46                 MatrixStack::projection().pop();
47         MatrixStack::modelview().pop();
48
49         Texturing::unbind();
50         Texture::unbind_from(0);
51         Material::unbind();
52         Program::unbind();
53         Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
54         WindingTest::unbind();
55 }
56
57 void Renderer::set_texture(const Texture *t)
58 {
59         state->texture = t;
60         state->texturing = 0;
61 }
62
63 void Renderer::set_texturing(const Texturing *t)
64 {
65         state->texturing = t;
66         state->texture = 0;
67 }
68
69 void Renderer::set_material(const Material *m)
70 {
71         state->material = m;
72 }
73
74 void Renderer::set_shader_program(const Program *p, const ProgramData *d)
75 {
76         state->shprog = p;
77         if(p && d)
78                 add_shader_data(*d);
79
80         /* Even if we have no new shdata, the existing ones need to be re-applied
81         to the new program */
82         shdata_changed = true;
83 }
84
85 void Renderer::add_shader_data(const ProgramData &d)
86 {
87         shdata_stack.push_back(&d);
88         state->shdata_count = shdata_stack.size();
89         shdata_changed = true;
90 }
91
92 void Renderer::set_vertex_array(const VertexArray *a)
93 {
94         vertex_array_changed = (a!=vertex_array);
95         vertex_array = a;
96 }
97
98 void Renderer::set_element_buffer(const Buffer *b)
99 {
100         element_buffer = b;
101 }
102
103 void Renderer::set_winding_test(const WindingTest *w)
104 {
105         state->winding_test = w;
106 }
107
108 void Renderer::push_state()
109 {
110         state_stack.push_back(state_stack.back());
111         state = &state_stack.back();
112         mtx_stack.push();
113 }
114
115 void Renderer::pop_state()
116 {
117         if(state_stack.size()==1)
118                 throw stack_underflow("Renderer::pop_state");
119
120         state_stack.pop_back();
121         state = &state_stack.back();
122         if(shdata_stack.size()>state->shdata_count)
123                 shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end());
124         mtx_stack.pop();
125         mtx_changed = true;
126         shdata_changed = true;
127 }
128
129 void Renderer::escape()
130 {
131         apply_state();
132         Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
133 }
134
135 void Renderer::draw(const Batch &batch)
136 {
137         if(!vertex_array)
138                 throw invalid_operation("Renderer::draw");
139
140         apply_state();
141
142         // Until VertexArray acquires VAO support and becomes Bindable
143         if(vertex_array_changed)
144         {
145                 vertex_array->apply();
146                 vertex_array_changed = false;
147         }
148
149         if(element_buffer)
150                 element_buffer->bind_to(ELEMENT_ARRAY_BUFFER);
151         else
152                 Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
153
154         batch.draw();
155 }
156
157 void Renderer::apply_state()
158 {
159         // We let the objects themselves figure out if the binding has changed
160
161         if(state->texturing)
162                 state->texturing->bind();
163         else
164         {
165                 Texturing::unbind();
166                 if(state->texture)
167                         state->texture->bind_to(0);
168                 else
169                         Texture::unbind_from(0);
170         }
171
172         if(state->material)
173                 state->material->bind();
174         else
175                 Material::unbind();
176
177         if(state->shprog)
178         {
179                 state->shprog->bind();
180                 if(shdata_changed)
181                 {
182                         for(vector<const ProgramData *>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
183                                 (*i)->apply();
184                         shdata_changed = false;
185                 }
186         }
187         else
188                 Program::unbind();
189
190         if(state->winding_test)
191                 state->winding_test->bind();
192         else
193                 WindingTest::unbind();
194
195         if(mtx_changed)
196         {
197                 MatrixStack::modelview() = mtx_stack.top();
198                 mtx_changed = false;
199         }
200 }
201
202
203 Renderer::State::State():
204         texture(0),
205         texturing(0),
206         material(0),
207         shprog(0),
208         shdata_count(0),
209         winding_test(0)
210 { }
211
212
213 Renderer::MtxStack::MtxStack(Renderer &r):
214         renderer(r)
215 { }
216
217 void Renderer::MtxStack::update()
218 {
219         renderer.mtx_changed = true;
220 }
221
222 } // namespace GL
223 } // namespace Msp