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;
52 void Sampler::update_parameter(int mask) const
62 if(!ARB_direct_state_access && TexUnit::current().get_texture()!=owner)
64 TexUnit *unit = TexUnit::find_unit(owner);
76 set_parameter_i(GL_TEXTURE_MIN_FILTER, min_filter);
78 set_parameter_i(GL_TEXTURE_MAG_FILTER, mag_filter);
79 if(mask&MAX_ANISOTROPY)
80 set_parameter_f(GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
82 set_parameter_i(GL_TEXTURE_WRAP_S, wrap_s);
84 set_parameter_i(GL_TEXTURE_WRAP_T, wrap_t);
86 set_parameter_i(GL_TEXTURE_WRAP_R, wrap_r);
89 set_parameter_i(GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
91 set_parameter_i(GL_TEXTURE_COMPARE_FUNC, cmp_func);
95 void Sampler::set_parameter_i(unsigned param, int value) const
98 glSamplerParameteri(id, param, value);
99 else if(ARB_direct_state_access)
100 glTextureParameteri(owner->get_id(), param, value);
102 glTexParameteri(owner->get_target(), param, value);
105 void Sampler::set_parameter_f(unsigned param, float value) const
108 glSamplerParameterf(id, param, value);
109 else if(ARB_direct_state_access)
110 glTextureParameterf(owner->get_id(), param, value);
112 glTexParameterf(owner->get_target(), param, value);
115 void Sampler::set_min_filter(TextureFilter f)
118 update_parameter(MIN_FILTER);
121 void Sampler::set_mag_filter(TextureFilter f)
124 update_parameter(MAG_FILTER);
127 void Sampler::set_filter(TextureFilter f)
130 set_mag_filter(f==NEAREST ? NEAREST : LINEAR);
133 void Sampler::set_max_anisotropy(float a)
136 throw invalid_argument("Sampler::set_max_anisotropy");
138 static Require _req(EXT_texture_filter_anisotropic);
140 if(EXT_texture_filter_anisotropic)
141 update_parameter(MAX_ANISOTROPY);
144 void Sampler::set_wrap(TextureWrap w)
152 void Sampler::set_wrap_s(TextureWrap w)
155 update_parameter(WRAP_S);
158 void Sampler::set_wrap_t(TextureWrap w)
161 update_parameter(WRAP_T);
164 void Sampler::set_wrap_r(TextureWrap w)
166 static Require _req(EXT_texture3D);
168 update_parameter(WRAP_R);
171 void Sampler::disable_compare()
174 update_parameter(COMPARE);
177 void Sampler::set_compare(Predicate f)
179 static Require _req(ARB_shadow);
182 update_parameter(COMPARE);
185 void Sampler::bind_to(unsigned i) const
187 TexUnit &unit = TexUnit::get_unit(i);
188 if(owner && owner!=unit.get_texture())
189 throw invalid_operation("Sampler::bind_to");
191 const Sampler *cur = unit.get_sampler();
192 if(unit.set_sampler(this))
194 if(!owner || (cur && cur->id))
195 glBindSampler(i, id);
199 update_parameter(dirty_params);
205 const Sampler *Sampler::current(unsigned i)
207 return TexUnit::get_unit(i).get_sampler();
210 void Sampler::unbind_from(unsigned i)
212 TexUnit &unit = TexUnit::get_unit(i);
213 const Sampler *cur = unit.get_sampler();
214 if(unit.set_sampler(0) && cur->id)
218 void Sampler::unload()
220 // TODO check which params actually need refreshing
226 Sampler::Loader::Loader(Sampler &s):
227 DataFile::ObjectLoader<Sampler>(s)
229 add("filter", &Loader::filter);
230 add("mag_filter", &Loader::mag_filter);
231 add("max_anisotropy", &Loader::max_anisotropy);
232 add("min_filter", &Loader::min_filter);
233 add("wrap", &Loader::wrap);
234 add("wrap_r", &Loader::wrap_r);
235 add("wrap_s", &Loader::wrap_s);
236 add("wrap_t", &Loader::wrap_t);
239 void Sampler::Loader::filter(TextureFilter f)
244 void Sampler::Loader::mag_filter(TextureFilter f)
246 obj.set_mag_filter(f);
249 void Sampler::Loader::max_anisotropy(float a)
251 obj.set_max_anisotropy(a);
254 void Sampler::Loader::min_filter(TextureFilter f)
256 obj.set_min_filter(f);
259 void Sampler::Loader::wrap(TextureWrap w)
264 void Sampler::Loader::wrap_r(TextureWrap w)
269 void Sampler::Loader::wrap_s(TextureWrap w)
274 void Sampler::Loader::wrap_t(TextureWrap w)
280 bool is_mipmapped(TextureFilter filter)
282 return (filter==NEAREST_MIPMAP_NEAREST || filter==NEAREST_MIPMAP_LINEAR ||
283 filter==LINEAR_MIPMAP_NEAREST || filter==LINEAR_MIPMAP_LINEAR);
286 void operator>>(const LexicalConverter &c, TextureFilter &tf)
288 if(c.get()=="NEAREST")
290 else if(c.get()=="LINEAR")
292 else if(c.get()=="NEAREST_MIPMAP_NEAREST")
293 tf = NEAREST_MIPMAP_NEAREST;
294 else if(c.get()=="NEAREST_MIPMAP_LINEAR")
295 tf = NEAREST_MIPMAP_LINEAR;
296 else if(c.get()=="LINEAR_MIPMAP_NEAREST")
297 tf = LINEAR_MIPMAP_NEAREST;
298 else if(c.get()=="LINEAR_MIPMAP_LINEAR")
299 tf = LINEAR_MIPMAP_LINEAR;
301 throw lexical_error(format("conversion of '%s' to TextureFilter", c.get()));
304 void operator>>(const LexicalConverter &c, TextureWrap &tw)
306 if(c.get()=="REPEAT")
308 else if(c.get()=="CLAMP_TO_EDGE")
310 else if(c.get()=="MIRRORED_REPEAT")
311 tw = MIRRORED_REPEAT;
313 throw lexical_error(format("conversion of '%s' to TextureWrap", c.get()));