]> git.tdb.fi Git - libs/gl.git/blob - source/builders/sequencebuilder.cpp
Set color write mask if no blending is used
[libs/gl.git] / source / builders / sequencebuilder.cpp
1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
3 #include <msp/strings/format.h>
4 #include "device.h"
5 #include "error.h"
6 #include "sequence.h"
7 #include "sequencebuilder.h"
8 #include "sequencetemplate.h"
9 #include "view.h"
10
11 using namespace std;
12
13 namespace Msp {
14 namespace GL {
15
16 SequenceBuilder::SequenceBuilder(const SequenceTemplate &t):
17         tmpl(t)
18 {
19         for(const SequenceTemplate::Renderable &r: tmpl.get_renderables())
20                 renderables[r.slot_name] = r.renderable;
21         for(const SequenceTemplate::PostProcessor &p: tmpl.get_postprocessors())
22                 if(!p.slot_name.empty())
23                         postprocessors[p.slot_name] = 0;
24 }
25
26 void SequenceBuilder::set_renderable(const string &name, Renderable &rend)
27 {
28         get_item(renderables, name) = &rend;
29 }
30
31 void SequenceBuilder::set_postprocessor(const string &name, PostProcessor &pproc)
32 {
33         get_item(postprocessors, name) = &pproc;
34 }
35
36 void SequenceBuilder::set_debug_name(const string &name)
37 {
38 #ifdef DEBUG
39         debug_name = name;
40 #else
41         (void)name;
42 #endif
43 }
44
45 void SequenceBuilder::build(Sequence &sequence) const
46 {
47 #ifdef DEBUG
48         if(!debug_name.empty())
49                 sequence.set_debug_name(debug_name);
50 #endif
51
52         map<string, Renderable *> final_renderables = renderables;
53         vector<const SequenceTemplate::Renderable *> sequences;
54         for(const SequenceTemplate::Renderable &r: tmpl.get_renderables())
55         {
56                 Renderable *&ptr = final_renderables[r.slot_name];
57                 if(!ptr)
58                 {
59                         if(r.effect_template)
60                         {
61                                 Effect *effect = r.effect_template->create(final_renderables);
62 #ifdef DEBUG
63                                 if(!debug_name.empty())
64                                         effect->set_debug_name(format("%s/%s", debug_name, r.slot_name));
65 #endif
66                                 ptr = effect;
67                         }
68                         else if(r.sequence_template)
69                         {
70                                 Sequence *seq = new Sequence;
71 #ifdef DEBUG
72                                 if(!debug_name.empty())
73                                         seq->set_debug_name(format("%s/%s", debug_name, r.slot_name));
74 #endif
75                                 ptr = seq;
76                                 sequences.push_back(&r);
77                         }
78                         else
79                                 throw invalid_operation("SequenceBuilder::build");
80
81                         sequence.add_owned(ptr);
82                 }
83         }
84
85         for(const SequenceTemplate::Renderable *s: sequences)
86         {
87                 SequenceBuilder bld(*s->sequence_template);
88                 for(const auto &kvp: s->sequence_renderables)
89                         if(Renderable *r = get_item(final_renderables, kvp.second))
90                                 bld.set_renderable(kvp.first, *r);
91                 bld.build(*static_cast<Sequence *>(get_item(final_renderables, s->slot_name)));
92         }
93
94         sequence.set_clear_enabled(tmpl.is_clear_enabled());
95         if(tmpl.is_clear_enabled())
96         {
97                 sequence.set_clear_colors(tmpl.get_clear_colors());
98                 sequence.set_clear_depth(tmpl.get_clear_depth());
99                 sequence.set_clear_stencil(tmpl.get_clear_stencil());
100         }
101
102         for(const SequenceTemplate::Step &s: tmpl.get_steps())
103         {
104                 // Existence is already ensured above
105                 Renderable &renderable = *get_item(final_renderables, s.renderable_name);
106                 Sequence::Step &step = sequence.add_step(s.tag, renderable);
107                 step.set_depth_test(s.depth_test);
108                 step.set_stencil_test(s.stencil_test);
109                 step.set_lighting(s.lighting);
110         }
111
112 #ifdef DEBUG
113         unsigned index = 0;
114 #endif
115         for(const SequenceTemplate::PostProcessor &p: tmpl.get_postprocessors())
116         {
117                 PostProcessor *proc = 0;
118                 if(!p.slot_name.empty())
119                         proc = get_item(postprocessors, p.slot_name);
120                 if(!proc)
121                 {
122                         if(p.postprocessor_template)
123                         {
124                                 proc = p.postprocessor_template->create(sequence.get_width(), sequence.get_height());
125 #ifdef DEBUG
126                                 if(!debug_name.empty())
127                                         proc->set_debug_name(format("%s/%d.pproc", debug_name, index++));
128 #endif
129                         }
130                         else
131                                 throw invalid_operation("SequenceBuilder::build");
132
133                         sequence.add_owned(proc);
134                 }
135
136                 sequence.add_postprocessor(*proc);
137         }
138 }
139
140 Sequence *SequenceBuilder::build() const
141 {
142         RefPtr<Sequence> sequence = new Sequence();
143         build(*sequence);
144         return sequence.release();
145 }
146
147 Sequence *SequenceBuilder::build(unsigned w, unsigned h) const
148 {
149         RefPtr<Sequence> sequence = create_sequence(w, h);
150         build(*sequence);
151         return sequence.release();
152 }
153
154 Sequence *SequenceBuilder::build(const View &view) const
155 {
156         RefPtr<Sequence> sequence = create_sequence(view.get_width(), view.get_height());
157         build(*sequence);
158         return sequence.release();
159 }
160
161 Sequence *SequenceBuilder::build(const Framebuffer &fbo) const
162 {
163         RefPtr<Sequence> sequence = create_sequence(fbo.get_width(), fbo.get_height());
164         build(*sequence);
165         return sequence.release();
166 }
167
168 Sequence * SequenceBuilder::create_sequence(unsigned w, unsigned h) const
169 {
170         if(!w || !h || tmpl.get_postprocessors().empty())
171                 return new Sequence;
172
173         unsigned samples = min(tmpl.get_maximum_multisample(), Device::get_current().get_info().limits.max_samples);
174         if(samples<tmpl.get_required_multisample())
175                 throw invalid_operation("SequenceBuilder::create_frame_format");
176
177         DataType color_type = (tmpl.get_hdr() ? HALF_FLOAT : UNSIGNED_BYTE);
178         PixelFormat color_pf = make_pixelformat(RGBA, color_type);
179
180         FrameFormat format = (COLOR_ATTACHMENT,color_pf, DEPTH_ATTACHMENT).set_samples(samples);
181         return new Sequence(w, h, format);
182 }
183
184 } // namespace GL
185 } // namespace Msp