1 #include <msp/gl/extensions/arb_direct_state_access.h>
2 #include <msp/gl/extensions/arb_texture_swizzle.h>
3 #include <msp/gl/extensions/ext_framebuffer_object.h>
4 #include <msp/io/memory.h>
7 #include "resourcemanager.h"
17 int Texture::swizzle_orders[] =
19 GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA,
20 GL_RED, GL_RED, GL_RED, GL_ONE,
21 GL_RED, GL_RED, GL_RED, GL_GREEN,
22 GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA
25 Texture::Texture(GLenum t, ResourceManager *m):
31 use_srgb_format(false),
32 auto_gen_mipmap(false),
33 default_sampler(*this)
43 while(TexUnit *unit = TexUnit::find_unit(this))
44 unbind_from(unit->get_index());
47 glDeleteTextures(1, &id);
50 void Texture::generate_id()
53 throw invalid_operation("Texture::generate_id");
54 if(ARB_direct_state_access)
55 glCreateTextures(target, 1, &id);
57 glGenTextures(1, &id);
60 void Texture::set_format(PixelFormat fmt)
62 PixelComponents comp = get_components(fmt);
63 PixelComponents st_comp = comp;
64 FormatSwizzle swiz = NO_SWIZZLE;
69 swiz = R_TO_LUMINANCE;
73 swiz = RG_TO_LUMINANCE_ALPHA;
86 PixelFormat st_fmt = make_pixelformat(st_comp, get_component_type(fmt), is_srgb(fmt));
87 require_pixelformat(st_fmt);
89 static Require _req(ARB_texture_swizzle);
96 void Texture::apply_swizzle()
98 if(swizzle==NO_SWIZZLE)
101 if(get_gl_api()==OPENGL_ES2)
103 set_parameter_i(GL_TEXTURE_SWIZZLE_R, swizzle_orders[swizzle*4]);
104 set_parameter_i(GL_TEXTURE_SWIZZLE_G, swizzle_orders[swizzle*4+1]);
105 set_parameter_i(GL_TEXTURE_SWIZZLE_B, swizzle_orders[swizzle*4+2]);
106 set_parameter_i(GL_TEXTURE_SWIZZLE_A, swizzle_orders[swizzle*4+3]);
110 if(ARB_direct_state_access)
111 glTextureParameteriv(id, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
113 glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
117 void Texture::set_parameter_i(GLenum param, int value) const
119 if(ARB_direct_state_access)
120 glTextureParameteri(id, param, value);
122 glTexParameteri(target, param, value);
125 void Texture::set_min_filter(TextureFilter f)
127 default_sampler.set_min_filter(f);
130 void Texture::set_mag_filter(TextureFilter f)
132 default_sampler.set_mag_filter(f);
135 void Texture::set_filter(TextureFilter f)
137 default_sampler.set_filter(f);
140 void Texture::set_max_anisotropy(float a)
142 default_sampler.set_max_anisotropy(a);
145 void Texture::set_wrap(TextureWrap w)
147 default_sampler.set_wrap(w);
150 void Texture::set_wrap_s(TextureWrap w)
152 default_sampler.set_wrap_s(w);
155 void Texture::set_wrap_t(TextureWrap w)
157 default_sampler.set_wrap_t(w);
160 void Texture::set_wrap_r(TextureWrap w)
162 default_sampler.set_wrap_r(w);
165 bool Texture::can_generate_mipmap()
167 return EXT_framebuffer_object;
170 void Texture::generate_mipmap()
172 // glGenerateMipmap is defined here
173 static Require _req(EXT_framebuffer_object);
175 if(ARB_direct_state_access)
176 glGenerateTextureMipmap(id);
179 BindRestore _bind(this);
180 glGenerateMipmap(target);
184 void Texture::set_auto_generate_mipmap(bool gm)
187 static Require _req(EXT_framebuffer_object);
189 auto_gen_mipmap = gm;
192 void Texture::set_compare_enabled(bool c)
195 default_sampler.set_compare(default_sampler.get_compare_function());
197 default_sampler.disable_compare();
200 void Texture::set_compare_func(Predicate f)
202 default_sampler.set_compare(f);
205 void Texture::load_image(const string &fn, bool)
210 void Texture::load_image(const string &fn, unsigned lv)
218 void Texture::image(const Graphics::Image &img, bool)
223 void Texture::bind_to(unsigned i) const
228 manager->resource_used(*this);
236 TexUnit &unit = TexUnit::get_unit(i);
237 const Texture *cur = unit.get_texture();
238 if(unit.set_texture(this))
241 manager->resource_used(*this);
243 if(ARB_direct_state_access)
244 glBindTextureUnit(i, id);
248 glBindTexture(target, id);
251 if(!unit.get_sampler() || unit.get_sampler()==&cur->default_sampler)
252 default_sampler.bind_to(i);
256 const Texture *Texture::current(unsigned i)
258 return TexUnit::get_unit(i).get_texture();
261 void Texture::unbind_from(unsigned i)
263 TexUnit &unit = TexUnit::get_unit(i);
264 const Texture *cur = unit.get_texture();
265 if(unit.set_texture(0))
267 if(ARB_direct_state_access)
268 glBindTextureUnit(i, 0);
272 glBindTexture(cur->target, 0);
275 if(unit.get_sampler()==&cur->default_sampler)
276 Sampler::unbind_from(i);
281 Texture::Loader::Loader(Texture &t):
282 DataFile::CollectionObjectLoader<Texture>(t, 0)
287 Texture::Loader::Loader(Texture &t, Collection &c):
288 DataFile::CollectionObjectLoader<Texture>(t, &c)
293 void Texture::Loader::init()
297 add("external_image", &Loader::external_image);
298 add("external_image_srgb", &Loader::external_image_srgb);
299 add("filter", &Loader::filter);
300 add("generate_mipmap", &Loader::generate_mipmap);
301 add("image_data", &Loader::image_data);
302 add("mag_filter", &Loader::mag_filter);
303 add("max_anisotropy", &Loader::max_anisotropy);
304 add("min_filter", &Loader::min_filter);
305 add("mipmap_levels", &Loader::mipmap_levels);
306 add("sampler", &Loader::sampler);
307 add("wrap", &Loader::wrap);
308 add("wrap_r", &Loader::wrap_r);
309 add("wrap_s", &Loader::wrap_s);
310 add("wrap_t", &Loader::wrap_t);
313 unsigned Texture::Loader::get_levels() const
315 return (is_mipmapped(obj.default_sampler.get_min_filter()) ? levels : 1);
318 #pragma GCC diagnostic push
319 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
320 void Texture::Loader::load_external_image(Graphics::Image &img, const string &fn)
322 RefPtr<IO::Seekable> io = get_collection().open_raw(fn);
324 throw IO::file_not_found(fn);
328 void Texture::Loader::external_image(const string &fn)
330 obj.use_srgb_format = false;
331 external_image_common(fn);
334 void Texture::Loader::external_image_srgb(const string &fn)
336 obj.use_srgb_format = true;
337 external_image_common(fn);
340 void Texture::Loader::external_image_common(const string &fn)
343 obj.manager->set_resource_location(obj, get_collection(), fn);
347 load_external_image(img, fn);
348 obj.image(img, get_levels());
352 void Texture::Loader::filter(TextureFilter f)
357 void Texture::Loader::generate_mipmap(bool gm)
359 obj.set_auto_generate_mipmap(gm);
362 void Texture::Loader::image_data(const string &data)
372 IO::Memory mem(data.data(), data.size());
375 obj.image(img, get_levels());
378 void Texture::Loader::mag_filter(TextureFilter f)
380 obj.set_mag_filter(f);
383 void Texture::Loader::max_anisotropy(float a)
385 obj.set_max_anisotropy(a);
388 void Texture::Loader::min_filter(TextureFilter f)
390 obj.set_min_filter(f);
393 void Texture::Loader::mipmap_levels(unsigned l)
398 void Texture::Loader::sampler()
400 load_sub(obj.default_sampler);
403 void Texture::Loader::wrap(TextureWrap w)
408 void Texture::Loader::wrap_r(TextureWrap w)
413 void Texture::Loader::wrap_s(TextureWrap w)
418 void Texture::Loader::wrap_t(TextureWrap w)
422 #pragma GCC diagnostic pop