]> git.tdb.fi Git - libs/gl.git/blob - source/render/sequence.cpp
Explicitly specify the target format of Sequence
[libs/gl.git] / source / render / sequence.cpp
1 #include <msp/core/maputils.h>
2 #include "blend.h"
3 #include "error.h"
4 #include "framebuffer.h"
5 #include "lighting.h"
6 #include "postprocessor.h"
7 #include "renderer.h"
8 #include "sequence.h"
9 #include "texture2d.h"
10 #include "view.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 Sequence::Sequence(unsigned w, unsigned h, const FrameFormat &f)
18 {
19         init(w, h, f);
20 }
21
22 Sequence::Sequence(const View &view, const FrameFormat &f)
23 {
24         init(view.get_width(), view.get_height(), f);
25 }
26
27 Sequence::Sequence(const Framebuffer &fbo, const FrameFormat &f)
28 {
29         init(fbo.get_width(), fbo.get_height(), f);
30 }
31
32 void Sequence::init(unsigned w, unsigned h, const FrameFormat &f)
33 {
34         width = w;
35         height = h;
36         target_format = f;
37
38         if(!target_format.empty())
39         {
40                 FrameFormat postproc_fmt = target_format;
41                 postproc_fmt.set_samples(1);
42                 target[0] = new RenderTarget(width, height, postproc_fmt);
43                 target[1] = new RenderTarget(width, height, postproc_fmt);
44
45                 if(target_format.get_samples()>1)
46                         target_ms = new RenderTarget(width, height, target_format);
47                 else
48                         target_ms = 0;
49         }
50         else
51         {
52                 target_ms = 0;
53                 target[0] = 0;
54                 target[1] = 0;
55         }
56 }
57
58 Sequence::~Sequence()
59 {
60         for(vector<PostProcStep>::iterator i=postproc.begin(); i!=postproc.end(); ++i)
61                 if(i->owned)
62                         delete i->postproc;
63         delete target[0];
64         delete target[1];
65         delete target_ms;
66 }
67
68 Sequence::Step &Sequence::add_step(Tag tag, Renderable &r)
69 {
70         steps.push_back(Step(tag, &r));
71         return steps.back();
72 }
73
74 void Sequence::add_postprocessor(PostProcessor &pp)
75 {
76         add_postprocessor(&pp, false);
77 }
78
79 void Sequence::add_postprocessor_owned(PostProcessor *pp)
80 {
81         add_postprocessor(pp, true);
82 }
83
84 void Sequence::add_postprocessor(PostProcessor *pp, bool owned)
85 {
86         if(target_format.empty())
87         {
88                 if(owned)
89                         delete pp;
90                 throw invalid_operation("Sequence::add_postprocessor");
91         }
92         postproc.push_back(PostProcStep(pp, owned));
93 }
94
95 void Sequence::setup_frame(Renderer &renderer)
96 {
97         for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
98                 if(Renderable *renderable = i->get_renderable())
99                         renderable->setup_frame(renderer);
100 }
101
102 void Sequence::finish_frame()
103 {
104         for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
105                 if(Renderable *renderable = i->get_renderable())
106                         renderable->finish_frame();
107 }
108
109 void Sequence::render(Renderer &renderer, Tag tag) const
110 {
111         if(tag.id)
112                 return;
113
114         Renderer::Push _push(renderer);
115
116         const Framebuffer *out_fbo = renderer.get_framebuffer();
117
118         if(target[0])
119         {
120                 renderer.set_framebuffer(&(target_ms ? target_ms : target[0])->get_framebuffer());
121                 renderer.clear();
122         }
123
124         for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
125         {
126                 Renderer::Push _push2(renderer);
127
128                 renderer.set_depth_test(&i->get_depth_test());
129                 renderer.set_stencil_test(&i->get_stencil_test());
130                 renderer.set_blend(&i->get_blend());
131
132                 if (const Lighting *lighting = i->get_lighting())
133                         renderer.add_shader_data(lighting->get_shader_data());
134                 renderer.set_clipping(i->get_clipping());
135
136                 if(const Renderable *renderable = i->get_renderable())
137                         renderer.render(*renderable, i->get_tag());
138         }
139
140         if(target[0])
141         {
142                 if(target_ms)
143                         renderer.resolve_multisample(target[0]->get_framebuffer(), COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
144
145                 renderer.set_depth_test(0);
146                 renderer.set_stencil_test(0);
147                 renderer.set_blend(0);
148
149                 for(unsigned i=0; i<postproc.size(); ++i)
150                 {
151                         unsigned j = i%2;
152                         renderer.set_framebuffer(i+1<postproc.size() ? &target[1-j]->get_framebuffer() : out_fbo);
153                         const Texture2D &color = target[j]->get_target_texture(COLOR_ATTACHMENT);
154                         const Texture2D &depth = target[j]->get_target_texture(DEPTH_ATTACHMENT);
155                         postproc[i].postproc->render(renderer, color, depth);
156                 }
157         }
158 }
159
160 void Sequence::set_debug_name(const string &name)
161 {
162 #ifdef DEBUG
163         for(unsigned i=0; i<2; ++i)
164                 if(target[i])
165                         target[i]->set_debug_name(format("%s [RT:%d]", name, i));
166         if(target_ms)
167                 target_ms->set_debug_name(name+" [RT:ms]");
168 #else
169         (void)name;
170 #endif
171 }
172
173
174 Sequence::Step::Step(Tag t, Renderable *r):
175         tag(t),
176         lighting(0),
177         clipping(0),
178         renderable(r)
179 { }
180
181 void Sequence::Step::set_lighting(const Lighting *l)
182 {
183         lighting = l;
184 }
185
186 void Sequence::Step::set_depth_test(const DepthTest &dt)
187 {
188         depth_test = dt;
189 }
190
191 void Sequence::Step::set_stencil_test(const StencilTest &st)
192 {
193         stencil_test = st;
194 }
195
196 void Sequence::Step::set_blend(const Blend &b)
197 {
198         blend = b;
199 }
200
201 void Sequence::Step::set_clipping(const Clipping *c)
202 {
203         clipping = c;
204 }
205
206 } // namespace GL
207 } // namespace Msp