]> git.tdb.fi Git - libs/gl.git/blob - source/renderpass.cpp
Add some missing virtual destructors and a base class copy-c'tor call
[libs/gl.git] / source / renderpass.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 <msp/core/refptr.h>
9 #include <msp/datafile/collection.h>
10 #include <msp/strings/formatter.h>
11 #include "material.h"
12 #include "renderpass.h"
13 #include "program.h"
14 #include "programdata.h"
15 #include "texture.h"
16 #include "texture2d.h"
17
18 using namespace std;
19
20 namespace Msp {
21 namespace GL {
22
23 RenderPass::RenderPass():
24         shprog(0),
25         shdata(0),
26         material(0)
27 { }
28
29 RenderPass::RenderPass(const RenderPass &other):
30         Bindable<RenderPass>(other),
31         shprog(other.shprog),
32         shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
33         material(other.material),
34         textures(other.textures)
35 { }
36
37 RenderPass::~RenderPass()
38 {
39         delete shdata;
40 }
41
42 void RenderPass::set_material(const Material *mat)
43 {
44         material = mat;
45 }
46
47 void RenderPass::set_texture(unsigned index, const Texture *tex)
48 {
49         for(vector<TextureSlot>::iterator i=textures.begin(); i!=textures.end(); ++i)
50                 if(i->index==index)
51                 {
52                         i->texture = tex;
53                         i->texture.keep();
54                         return;
55                 }
56
57         throw KeyError("No texture slot for that unit", lexical_cast(index));
58 }
59
60 void RenderPass::bind() const
61 {
62         const RenderPass *old = current();
63         if(!set_current(this))
64                 return;
65
66         if(shprog)
67         {
68                 shprog->bind();
69                 shdata->apply();
70         }
71         else if(old && old->shprog)
72                 GL::Program::unbind();
73
74         if(material)
75                 material->bind();
76         else if(old && old->material)
77                 GL::Material::unbind();
78
79         unsigned used_tex_units = 0;
80         for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
81         {
82                 i->texture->bind_to(i->index);
83                 used_tex_units |= 1<<i->index;
84         }
85         if(old)
86         {
87                 for(vector<TextureSlot>::const_iterator i=old->textures.begin(); i!=old->textures.end(); ++i)
88                         if(!used_tex_units&(1<<i->index))
89                                 Texture::unbind_from(i->index);
90         }
91 }
92
93 void RenderPass::unbind()
94 {
95         const RenderPass *old = current();
96         if(!set_current(0))
97                 return;
98
99         if(old->shprog)
100                 GL::Program::unbind();
101
102         if(old->material)
103                 GL::Material::unbind();
104
105         for(unsigned i=old->textures.size(); i--; )
106                 GL::Texture::unbind_from(i);
107 }
108
109
110 RenderPass::TextureSlot::TextureSlot(unsigned i):
111         index(i),
112         texture(0)
113 { }
114
115
116 RenderPass::Loader::Loader(RenderPass &p):
117         DataFile::CollectionObjectLoader<RenderPass>(p, 0)
118 {
119         init();
120 }
121
122 RenderPass::Loader::Loader(RenderPass &p, Collection &c):
123         DataFile::CollectionObjectLoader<RenderPass>(p, &c)
124 {
125         init();
126 }
127
128 void RenderPass::Loader::init()
129 {
130         allow_pointer_reload = false;
131
132         add("shader",   &RenderPass::shprog);
133         add("material", static_cast<void (Loader::*)()>(&Loader::material));
134         add("material", static_cast<void (Loader::*)(const string &)>(&Loader::material));
135         add("texunit",  &Loader::texunit);
136         add("uniforms", &Loader::uniforms);
137 }
138
139 void RenderPass::Loader::finish()
140 {
141         // XXX Make shdata optional
142         if(obj.shprog && !obj.shdata)
143                 obj.shdata = new ProgramData;
144 }
145
146 void RenderPass::Loader::material()
147 {
148         RefPtr<Material> mat = new Material;
149         load_sub(*mat);
150         obj.material = mat;
151 }
152
153 void RenderPass::Loader::material(const string &name)
154 {
155         obj.material = get_collection().get<Material>(name);
156         obj.material.keep();
157 }
158
159 void RenderPass::Loader::texunit(unsigned i)
160 {
161         TextureSlot slot(i);
162         load_sub(slot);
163         obj.textures.push_back(slot);
164 }
165
166 void RenderPass::Loader::uniforms()
167 {
168         if(!obj.shprog)
169                 throw InvalidState("Can't load uniforms without a shader program");
170         if(!obj.shdata)
171                 obj.shdata = new ProgramData;
172         load_sub(*obj.shdata, *obj.shprog);
173 }
174
175
176 RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
177         DataFile::CollectionObjectLoader<TextureSlot>(s, 0)
178 {
179         init();
180 }
181
182 RenderPass::TextureSlot::Loader::Loader(TextureSlot &s, Collection &c):
183         DataFile::CollectionObjectLoader<TextureSlot>(s, &c)
184 {
185         init();
186 }
187
188 void RenderPass::TextureSlot::Loader::init()
189 {
190         add("texture",   &Loader::texture);
191         add("texture2d", &Loader::texture2d);
192 }
193
194 void RenderPass::TextureSlot::Loader::texture(const string &name)
195 {
196         obj.texture = get_collection().get<Texture>(name);
197         obj.texture.keep();
198 }
199
200 void RenderPass::TextureSlot::Loader::texture2d()
201 {
202         RefPtr<Texture2D> tex = new Texture2D;
203         load_sub(*tex);
204         obj.texture = tex;
205 }
206
207 } // namespace GL
208 } // namespace Msp