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/gl/extensions/khr_debug.h>
5 #include <msp/io/memory.h>
7 #include "resourcemanager.h"
16 const int Texture::swizzle_orders[] =
18 GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA,
19 GL_RED, GL_RED, GL_RED, GL_ONE,
20 GL_RED, GL_RED, GL_RED, GL_GREEN,
21 GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA
24 Texture *Texture::scratch_binding = 0;
26 Texture::Texture(GLenum t, ResourceManager *m):
29 format(NO_PIXELFORMAT),
32 use_srgb_format(false),
33 auto_gen_mipmap(false)
40 static bool alignment_init = false;
43 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
44 alignment_init = true;
50 if(this==scratch_binding)
53 glDeleteTextures(1, &id);
56 void Texture::generate_id()
59 throw invalid_operation("Texture::generate_id");
60 if(ARB_direct_state_access)
61 glCreateTextures(target, 1, &id);
63 glGenTextures(1, &id);
66 if(!debug_name.empty() && KHR_debug)
67 glObjectLabel(GL_TEXTURE, id, debug_name.size(), debug_name.c_str());
71 void Texture::set_format(PixelFormat fmt)
73 PixelComponents comp = get_components(fmt);
74 PixelComponents st_comp = comp;
75 FormatSwizzle swiz = NO_SWIZZLE;
80 swiz = R_TO_LUMINANCE;
84 swiz = RG_TO_LUMINANCE_ALPHA;
97 PixelFormat st_fmt = make_pixelformat(st_comp, get_component_type(fmt), is_srgb(fmt));
98 require_pixelformat(st_fmt);
100 static Require _req(ARB_texture_swizzle);
103 storage_fmt = st_fmt;
107 void Texture::apply_swizzle()
109 if(swizzle==NO_SWIZZLE)
112 if(get_gl_api()==OPENGL_ES2)
114 set_parameter_i(GL_TEXTURE_SWIZZLE_R, swizzle_orders[swizzle*4]);
115 set_parameter_i(GL_TEXTURE_SWIZZLE_G, swizzle_orders[swizzle*4+1]);
116 set_parameter_i(GL_TEXTURE_SWIZZLE_B, swizzle_orders[swizzle*4+2]);
117 set_parameter_i(GL_TEXTURE_SWIZZLE_A, swizzle_orders[swizzle*4+3]);
121 if(ARB_direct_state_access)
122 glTextureParameteriv(id, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
124 glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
128 void Texture::set_parameter_i(GLenum param, int value) const
130 if(ARB_direct_state_access)
131 glTextureParameteri(id, param, value);
133 glTexParameteri(target, param, value);
136 void Texture::generate_mipmap()
138 // glGenerateMipmap is defined here
139 static Require _req(EXT_framebuffer_object);
141 if(ARB_direct_state_access)
142 glGenerateTextureMipmap(id);
146 glGenerateMipmap(target);
150 void Texture::load_image(const string &fn, unsigned lv)
158 void Texture::set_debug_name(const string &name)
163 glObjectLabel(GL_TEXTURE, id, name.size(), name.c_str());
169 void Texture::bind_scratch()
172 glActiveTexture(GL_TEXTURE0);
173 if(scratch_binding!=this)
175 if(scratch_binding && scratch_binding->target!=target)
176 glBindTexture(scratch_binding->target, 0);
177 glBindTexture(target, id);
178 scratch_binding = this;
182 void Texture::unbind_scratch()
186 glBindTexture(scratch_binding->target, 0);
192 Texture::Loader::Loader(Texture &t):
193 DataFile::CollectionObjectLoader<Texture>(t, 0)
198 Texture::Loader::Loader(Texture &t, Collection &c):
199 DataFile::CollectionObjectLoader<Texture>(t, &c)
204 void Texture::Loader::init()
208 add("external_image", &Loader::external_image);
209 add("external_image_srgb", &Loader::external_image_srgb);
210 add("generate_mipmap", &Loader::generate_mipmap);
211 add("image_data", &Loader::image_data);
212 add("mipmap_levels", &Loader::mipmap_levels);
215 void Texture::Loader::finish()
217 if(obj.auto_gen_mipmap)
218 obj.generate_mipmap();
221 void Texture::Loader::load_external_image(Graphics::Image &img, const string &fn)
223 RefPtr<IO::Seekable> io = get_collection().open_raw(fn);
225 throw IO::file_not_found(fn);
229 void Texture::Loader::external_image(const string &fn)
231 obj.use_srgb_format = false;
232 external_image_common(fn);
235 void Texture::Loader::external_image_srgb(const string &fn)
237 obj.use_srgb_format = true;
238 external_image_common(fn);
241 void Texture::Loader::external_image_common(const string &fn)
244 obj.manager->set_resource_location(obj, get_collection(), fn);
248 load_external_image(img, fn);
249 obj.image(img, levels);
253 void Texture::Loader::generate_mipmap(bool gm)
255 obj.auto_gen_mipmap = gm;
258 void Texture::Loader::image_data(const string &data)
268 IO::Memory mem(data.data(), data.size());
271 obj.image(img, levels);
274 void Texture::Loader::mipmap_levels(unsigned l)