1 #include <msp/gl/extensions/arb_direct_state_access.h>
2 #include <msp/gl/extensions/arb_sampler_objects.h>
3 #include <msp/gl/extensions/arb_shadow.h>
4 #include <msp/gl/extensions/ext_texture_filter_anisotropic.h>
5 #include <msp/gl/extensions/ext_texture3d.h>
6 #include <msp/strings/format.h>
22 Require _req(ARB_sampler_objects);
23 if(ARB_direct_state_access)
24 glCreateSamplers(1, &id);
26 glGenSamplers(1, &id);
29 Sampler::Sampler(const Texture &tex):
33 if(this!=&tex.get_default_sampler())
34 throw invalid_argument("Sampler::Sampler");
41 min_filter = NEAREST_MIPMAP_LINEAR;
43 max_anisotropy = 1.0f;
47 border_color = Color(0.0f, 0.0f, 0.0f, 0.0f);
53 void Sampler::update_parameter(int mask) const
63 if(!ARB_direct_state_access && TexUnit::current().get_texture()!=owner)
65 TexUnit *unit = TexUnit::find_unit(owner);
77 set_parameter_i(GL_TEXTURE_MIN_FILTER, min_filter);
79 set_parameter_i(GL_TEXTURE_MAG_FILTER, mag_filter);
80 if(mask&MAX_ANISOTROPY)
81 set_parameter_f(GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
83 set_parameter_i(GL_TEXTURE_WRAP_S, wrap_s);
85 set_parameter_i(GL_TEXTURE_WRAP_T, wrap_t);
87 set_parameter_i(GL_TEXTURE_WRAP_R, wrap_r);
89 set_parameter_fv(GL_TEXTURE_BORDER_COLOR, &border_color.r);
92 set_parameter_i(GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
94 set_parameter_i(GL_TEXTURE_COMPARE_FUNC, cmp_func);
98 void Sampler::set_parameter_i(unsigned param, int value) const
101 glSamplerParameteri(id, param, value);
102 else if(ARB_direct_state_access)
103 glTextureParameteri(owner->get_id(), param, value);
105 glTexParameteri(owner->get_target(), param, value);
108 void Sampler::set_parameter_f(unsigned param, float value) const
111 glSamplerParameterf(id, param, value);
112 else if(ARB_direct_state_access)
113 glTextureParameterf(owner->get_id(), param, value);
115 glTexParameterf(owner->get_target(), param, value);
118 void Sampler::set_parameter_fv(unsigned param, const float *value) const
121 glSamplerParameterfv(id, param, value);
122 else if(ARB_direct_state_access)
123 glTextureParameterfv(owner->get_id(), param, value);
125 glTexParameterfv(owner->get_target(), param, value);
128 void Sampler::set_min_filter(TextureFilter f)
131 update_parameter(MIN_FILTER);
134 void Sampler::set_mag_filter(TextureFilter f)
137 update_parameter(MAG_FILTER);
140 void Sampler::set_filter(TextureFilter f)
143 set_mag_filter(f==NEAREST ? NEAREST : LINEAR);
146 void Sampler::set_max_anisotropy(float a)
149 throw invalid_argument("Sampler::set_max_anisotropy");
151 static Require _req(EXT_texture_filter_anisotropic);
153 if(EXT_texture_filter_anisotropic)
154 update_parameter(MAX_ANISOTROPY);
157 void Sampler::set_wrap(TextureWrap w)
165 void Sampler::set_wrap_s(TextureWrap w)
168 update_parameter(WRAP_S);
171 void Sampler::set_wrap_t(TextureWrap w)
174 update_parameter(WRAP_T);
177 void Sampler::set_wrap_r(TextureWrap w)
179 static Require _req(EXT_texture3D);
181 update_parameter(WRAP_R);
184 void Sampler::set_border_color(const Color &c)
187 update_parameter(BORDER_COLOR);
190 void Sampler::disable_compare()
193 update_parameter(COMPARE);
196 void Sampler::set_compare(Predicate f)
198 static Require _req(ARB_shadow);
201 update_parameter(COMPARE);
204 void Sampler::bind_to(unsigned i) const
206 TexUnit &unit = TexUnit::get_unit(i);
207 if(owner && owner!=unit.get_texture())
208 throw invalid_operation("Sampler::bind_to");
210 const Sampler *cur = unit.get_sampler();
211 if(unit.set_sampler(this))
213 if(!owner || (cur && cur->id))
214 glBindSampler(i, id);
218 update_parameter(dirty_params);
224 const Sampler *Sampler::current(unsigned i)
226 return TexUnit::get_unit(i).get_sampler();
229 void Sampler::unbind_from(unsigned i)
231 TexUnit &unit = TexUnit::get_unit(i);
232 const Sampler *cur = unit.get_sampler();
233 if(unit.set_sampler(0) && cur->id)
237 void Sampler::unload()
239 if(owner && !owner->get_id())
241 if(min_filter!=NEAREST_MIPMAP_LINEAR)
242 dirty_params |= MIN_FILTER;
243 if(mag_filter!=LINEAR)
244 dirty_params |= MAG_FILTER;
245 if(max_anisotropy!=1.0f)
246 dirty_params |= MAX_ANISOTROPY;
248 dirty_params |= WRAP_S;
250 dirty_params |= WRAP_T;
252 dirty_params |= WRAP_R;
253 if(compare || cmp_func!=LEQUAL)
254 dirty_params |= COMPARE;
259 Sampler::Loader::Loader(Sampler &s):
260 DataFile::ObjectLoader<Sampler>(s)
262 add("border_color", &Loader::border_color);
263 add("compare", &Loader::compare);
264 add("filter", &Loader::filter);
265 add("mag_filter", &Loader::mag_filter);
266 add("max_anisotropy", &Loader::max_anisotropy);
267 add("min_filter", &Loader::min_filter);
268 add("wrap", &Loader::wrap);
269 add("wrap_r", &Loader::wrap_r);
270 add("wrap_s", &Loader::wrap_s);
271 add("wrap_t", &Loader::wrap_t);
274 void Sampler::Loader::border_color(float r, float g, float b, float a)
276 obj.set_border_color(Color(r, g, b, a));
279 void Sampler::Loader::compare(Predicate c)
284 void Sampler::Loader::filter(TextureFilter f)
289 void Sampler::Loader::mag_filter(TextureFilter f)
291 obj.set_mag_filter(f);
294 void Sampler::Loader::max_anisotropy(float a)
296 obj.set_max_anisotropy(a);
299 void Sampler::Loader::min_filter(TextureFilter f)
301 obj.set_min_filter(f);
304 void Sampler::Loader::wrap(TextureWrap w)
309 void Sampler::Loader::wrap_r(TextureWrap w)
314 void Sampler::Loader::wrap_s(TextureWrap w)
319 void Sampler::Loader::wrap_t(TextureWrap w)
325 bool is_mipmapped(TextureFilter filter)
327 return (filter==NEAREST_MIPMAP_NEAREST || filter==NEAREST_MIPMAP_LINEAR ||
328 filter==LINEAR_MIPMAP_NEAREST || filter==LINEAR_MIPMAP_LINEAR);
331 void operator>>(const LexicalConverter &c, TextureFilter &tf)
333 if(c.get()=="NEAREST")
335 else if(c.get()=="LINEAR")
337 else if(c.get()=="NEAREST_MIPMAP_NEAREST")
338 tf = NEAREST_MIPMAP_NEAREST;
339 else if(c.get()=="NEAREST_MIPMAP_LINEAR")
340 tf = NEAREST_MIPMAP_LINEAR;
341 else if(c.get()=="LINEAR_MIPMAP_NEAREST")
342 tf = LINEAR_MIPMAP_NEAREST;
343 else if(c.get()=="LINEAR_MIPMAP_LINEAR")
344 tf = LINEAR_MIPMAP_LINEAR;
346 throw lexical_error(format("conversion of '%s' to TextureFilter", c.get()));
349 void operator>>(const LexicalConverter &c, TextureWrap &tw)
351 if(c.get()=="REPEAT")
353 else if(c.get()=="CLAMP_TO_EDGE")
355 else if(c.get()=="CLAMP_TO_BORDER")
356 tw = CLAMP_TO_BORDER;
357 else if(c.get()=="MIRRORED_REPEAT")
358 tw = MIRRORED_REPEAT;
360 throw lexical_error(format("conversion of '%s' to TextureWrap", c.get()));