]> git.tdb.fi Git - libs/gl.git/blob - source/core/blend.cpp
Add color write mask to blend state
[libs/gl.git] / source / core / blend.cpp
1 #include <msp/gl/extensions/ext_blend_minmax.h>
2 #include <msp/gl/extensions/ext_blend_subtract.h>
3 #include <msp/strings/format.h>
4 #include <msp/strings/utils.h>
5 #include "blend.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 Blend::Blend():
13         enabled(false),
14         equation(ADD),
15         src_factor(ONE),
16         dst_factor(ZERO),
17         constant(0.0f, 0.0f, 0.0f, 0.0f),
18         write_mask(WRITE_ALL)
19 { }
20
21 Blend::Blend(BlendFactor sf, BlendFactor df):
22         enabled(true),
23         equation(ADD),
24         src_factor(sf),
25         dst_factor(df),
26         constant(0.0f, 0.0f, 0.0f, 0.0f),
27         write_mask(WRITE_ALL)
28 { }
29
30 Blend::Blend(BlendEquation e, BlendFactor sf, BlendFactor df):
31         enabled(true),
32         equation(e),
33         src_factor(sf),
34         dst_factor(df),
35         constant(0.0f, 0.0f, 0.0f, 0.0f),
36         write_mask(WRITE_ALL)
37 { }
38
39
40 Blend::Loader::Loader(Blend &b):
41         ObjectLoader<Blend>(b)
42 {
43         add("equation", &Loader::equation);
44         add("factors", &Loader::factors);
45         add("constant", &Loader::constant);
46 }
47
48 void Blend::Loader::constant(float r, float g, float b, float a)
49 {
50         obj.constant = Color(r, g, b, a);
51 }
52
53 void Blend::Loader::equation(BlendEquation eq)
54 {
55         obj.enabled = true;
56         obj.equation = eq;
57 }
58
59 void Blend::Loader::factors(BlendFactor sf, BlendFactor df)
60 {
61         obj.enabled = true;
62         obj.src_factor = sf;
63         obj.dst_factor = df;
64 }
65
66
67 unsigned get_gl_blend_equation(BlendEquation eq)
68 {
69         switch(eq)
70         {
71         case ADD: return GL_FUNC_ADD;
72         case SUBTRACT: return GL_FUNC_SUBTRACT;
73         case REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
74         case MIN: return GL_MIN;
75         case MAX: return GL_MAX;
76         default: throw invalid_argument("get_gl_blend_equation");
77         }
78 }
79
80 unsigned get_gl_blend_factor(BlendFactor factor)
81 {
82         switch(factor)
83         {
84         case ZERO: return GL_ZERO;
85         case ONE: return GL_ONE;
86         case SRC_COLOR: return GL_SRC_COLOR;
87         case ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
88         case SRC_ALPHA: return GL_SRC_ALPHA;
89         case ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
90         case DST_COLOR: return GL_DST_COLOR;
91         case ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
92         case DST_ALPHA: return GL_DST_ALPHA;
93         case ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
94         case CONSTANT_COLOR: return GL_CONSTANT_COLOR;
95         case ONE_MINUS_CONSTANT_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
96         case CONSTANT_ALPHA: return GL_CONSTANT_ALPHA;
97         case ONE_MINUS_CONSTANT_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
98         default: throw invalid_argument("get_gl_blend_factor");
99         }
100 }
101
102 void operator>>(const LexicalConverter &conv, BlendEquation &eq)
103 {
104         const string &str = conv.get();
105         if(str=="ADD")
106                 eq = ADD;
107         else if(str=="SUBTRACT")
108                 eq = SUBTRACT;
109         else if(str=="REVERSE_SUBTRACT")
110                 eq = REVERSE_SUBTRACT;
111         else if(str=="MIN")
112                 eq = MIN;
113         else if(str=="MAX")
114                 eq = MAX;
115         else
116                 throw lexical_error(format("conversion of '%s' to BlendEquation", str));
117 }
118
119 void operator<<(LexicalConverter &conv, BlendEquation eq)
120 {
121         switch(eq)
122         {
123         case ADD: conv.result("ADD"); break;
124         case SUBTRACT: conv.result("SUBTRACT"); break;
125         case REVERSE_SUBTRACT: conv.result("REVERSE_SUBTRACT"); break;
126         case MIN: conv.result("MIN"); break;
127         case MAX: conv.result("MAX"); break;
128         default: conv.result(format("BlendEquation(%#x)", static_cast<int>(eq)));
129         }
130 }
131
132 void operator>>(const LexicalConverter &conv, BlendFactor &factor)
133 {
134         const string &str = conv.get();
135         if(str=="ZERO")
136                 factor = ZERO;
137         else if(str=="ONE")
138                 factor = ONE;
139         else if(str=="SRC_COLOR")
140                 factor = SRC_COLOR;
141         else if(str=="ONE_MINUS_SRC_COLOR")
142                 factor = ONE_MINUS_SRC_COLOR;
143         else if(str=="SRC_ALPHA")
144                 factor = SRC_ALPHA;
145         else if(str=="ONE_MINUS_SRC_ALPHA")
146                 factor = ONE_MINUS_SRC_ALPHA;
147         else if(str=="DST_COLOR")
148                 factor = DST_COLOR;
149         else if(str=="ONE_MINUS_DST_COLOR")
150                 factor = ONE_MINUS_DST_COLOR;
151         else if(str=="DST_ALPHA")
152                 factor = DST_ALPHA;
153         else if(str=="ONE_MINUS_DST_ALPHA")
154                 factor = ONE_MINUS_DST_ALPHA;
155         else if(str=="CONSTANT_COLOR")
156                 factor = CONSTANT_COLOR;
157         else if(str=="ONE_MINUS_CONSTANT_COLOR")
158                 factor = ONE_MINUS_CONSTANT_COLOR;
159         else if(str=="CONSTANT_ALPHA")
160                 factor = CONSTANT_ALPHA;
161         else if(str=="ONE_MINUS_CONSTANT_ALPHA")
162                 factor = ONE_MINUS_CONSTANT_ALPHA;
163         else
164                 throw lexical_error(format("conversion of '%s' to BlendFactor", str));
165 }
166
167 void operator<<(LexicalConverter &conv, BlendFactor factor)
168 {
169         switch(factor)
170         {
171         case ZERO: conv.result("ZERO"); break;
172         case ONE: conv.result("ONE"); break;
173         case SRC_COLOR: conv.result("SRC_COLOR"); break;
174         case ONE_MINUS_SRC_COLOR: conv.result("ONE_MINUS_SRC_COLOR"); break;
175         case SRC_ALPHA: conv.result("SRC_ALPHA"); break;
176         case ONE_MINUS_SRC_ALPHA: conv.result("ONE_MINUS_SRC_ALPHA"); break;
177         case DST_COLOR: conv.result("DST_COLOR"); break;
178         case ONE_MINUS_DST_COLOR: conv.result("ONE_MINUS_DST_COLOR"); break;
179         case DST_ALPHA: conv.result("DST_ALPHA"); break;
180         case ONE_MINUS_DST_ALPHA: conv.result("ONE_MINUS_DST_ALPHA"); break;
181         case CONSTANT_COLOR: conv.result("CONSTANT_COLOR"); break;
182         case ONE_MINUS_CONSTANT_COLOR: conv.result("ONE_MINUS_CONSTANT_COLOR"); break;
183         case CONSTANT_ALPHA: conv.result("CONSTANT_ALPHA"); break;
184         case ONE_MINUS_CONSTANT_ALPHA: conv.result("ONE_MINUS_CONSTANT_ALPHA"); break;
185         default: conv.result(format("BlendFactor(%#x)", static_cast<int>(factor)));
186         }
187 }
188
189 void operator>>(const LexicalConverter &conv, ColorWriteMask &mask)
190 {
191         ColorWriteMask result = WRITE_NONE;
192         for(const string &p: split(conv.get(), '_'))
193         {
194                 if(p=="ALL")
195                         result = result|WRITE_ALL;
196                 else if(p=="RED")
197                         result = result|WRITE_RED;
198                 else if(p=="GREEN")
199                         result = result|WRITE_GREEN;
200                 else if(p=="BLUE")
201                         result = result|WRITE_BLUE;
202                 else if(p=="ALPHA")
203                         result = result|WRITE_ALPHA;
204                 else
205                         throw lexical_error(format("conversion of '%s' to ColorWriteMask", conv.get()));
206         }
207         mask = result;
208 }
209
210 void operator<<(LexicalConverter &conv, ColorWriteMask mask)
211 {
212         if(mask==WRITE_ALL)
213                 conv.result("ALL");
214         else if(mask&~WRITE_ALL)
215                 conv.result(format("ColorWriteMask(%#x)", static_cast<int>(mask)));
216         else
217         {
218                 string result;
219                 if(mask&WRITE_RED)
220                         result = "RED";
221                 if(mask&WRITE_GREEN)
222                         append(result, "_", "GREEN");
223                 if(mask&WRITE_BLUE)
224                         append(result, "_", "BLUE");
225                 if(mask&WRITE_ALPHA)
226                         append(result, "_", "ALPHA");
227                 conv.result(result);
228         }
229 }
230
231 } // namespace GL
232 } // namespace Msp