]> git.tdb.fi Git - libs/gl.git/blob - source/renderpass.cpp
Use RefPtrs in Object
[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         material.keep();
46 }
47
48 void RenderPass::set_texture(unsigned index, const Texture *tex)
49 {
50         for(vector<TextureSlot>::iterator i=textures.begin(); i!=textures.end(); ++i)
51                 if(i->index==index)
52                 {
53                         i->texture = tex;
54                         i->texture.keep();
55                         return;
56                 }
57
58         textures.push_back(TextureSlot(index));
59         textures.back().texture = tex;
60         textures.back().texture.keep();
61 }
62
63 void RenderPass::bind() const
64 {
65         const RenderPass *old = current();
66         if(!set_current(this))
67                 return;
68
69         if(shprog)
70         {
71                 shprog->bind();
72                 shdata->apply();
73         }
74         else if(old && old->shprog)
75                 GL::Program::unbind();
76
77         if(material)
78                 material->bind();
79         else if(old && old->material)
80                 GL::Material::unbind();
81
82         unsigned used_tex_units = 0;
83         for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
84         {
85                 i->texture->bind_to(i->index);
86                 used_tex_units |= 1<<i->index;
87         }
88         if(old)
89         {
90                 for(vector<TextureSlot>::const_iterator i=old->textures.begin(); i!=old->textures.end(); ++i)
91                         if(!used_tex_units&(1<<i->index))
92                                 Texture::unbind_from(i->index);
93         }
94 }
95
96 void RenderPass::unbind()
97 {
98         const RenderPass *old = current();
99         if(!set_current(0))
100                 return;
101
102         if(old->shprog)
103                 GL::Program::unbind();
104
105         if(old->material)
106                 GL::Material::unbind();
107
108         for(unsigned i=old->textures.size(); i--; )
109                 GL::Texture::unbind_from(i);
110 }
111
112
113 RenderPass::TextureSlot::TextureSlot(unsigned i):
114         index(i),
115         texture(0)
116 { }
117
118
119 RenderPass::Loader::Loader(RenderPass &p):
120         DataFile::CollectionObjectLoader<RenderPass>(p, 0)
121 {
122         init();
123 }
124
125 RenderPass::Loader::Loader(RenderPass &p, Collection &c):
126         DataFile::CollectionObjectLoader<RenderPass>(p, &c)
127 {
128         init();
129 }
130
131 void RenderPass::Loader::init()
132 {
133         allow_pointer_reload = false;
134
135         add("shader",   &RenderPass::shprog);
136         add("material", static_cast<void (Loader::*)()>(&Loader::material));
137         add("material", static_cast<void (Loader::*)(const string &)>(&Loader::material));
138         add("texunit",  &Loader::texunit);
139         add("uniforms", &Loader::uniforms);
140 }
141
142 void RenderPass::Loader::finish()
143 {
144         // XXX Make shdata optional
145         if(obj.shprog && !obj.shdata)
146                 obj.shdata = new ProgramData;
147 }
148
149 void RenderPass::Loader::material()
150 {
151         RefPtr<Material> mat = new Material;
152         load_sub(*mat);
153         obj.material = mat;
154 }
155
156 void RenderPass::Loader::material(const string &name)
157 {
158         obj.material = get_collection().get<Material>(name);
159         obj.material.keep();
160 }
161
162 void RenderPass::Loader::texunit(unsigned i)
163 {
164         TextureSlot slot(i);
165         load_sub(slot);
166         obj.textures.push_back(slot);
167 }
168
169 void RenderPass::Loader::uniforms()
170 {
171         if(!obj.shprog)
172                 throw InvalidState("Can't load uniforms without a shader program");
173         if(!obj.shdata)
174                 obj.shdata = new ProgramData;
175         load_sub(*obj.shdata, *obj.shprog);
176 }
177
178
179 RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
180         DataFile::CollectionObjectLoader<TextureSlot>(s, 0)
181 {
182         init();
183 }
184
185 RenderPass::TextureSlot::Loader::Loader(TextureSlot &s, Collection &c):
186         DataFile::CollectionObjectLoader<TextureSlot>(s, &c)
187 {
188         init();
189 }
190
191 void RenderPass::TextureSlot::Loader::init()
192 {
193         add("texture",   &Loader::texture);
194         add("texture2d", &Loader::texture2d);
195 }
196
197 void RenderPass::TextureSlot::Loader::texture(const string &name)
198 {
199         obj.texture = get_collection().get<Texture>(name);
200         obj.texture.keep();
201 }
202
203 void RenderPass::TextureSlot::Loader::texture2d()
204 {
205         RefPtr<Texture2D> tex = new Texture2D;
206         load_sub(*tex);
207         obj.texture = tex;
208 }
209
210 } // namespace GL
211 } // namespace Msp