]> git.tdb.fi Git - libs/gl.git/blob - source/texture.cpp
Depracate the srgb parameter of Texture::image functions
[libs/gl.git] / source / texture.cpp
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>
5 #include "bindable.h"
6 #include "error.h"
7 #include "resourcemanager.h"
8 #include "resources.h"
9 #include "texture.h"
10 #include "texunit.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 int Texture::swizzle_orders[] =
18 {
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
23 };
24
25 Texture::Texture(GLenum t, ResourceManager *m):
26         id(0),
27         target(t),
28         format(RGB8),
29         storage_fmt(RGB8),
30         swizzle(NO_SWIZZLE),
31         auto_gen_mipmap(false),
32         default_sampler(*this)
33 {
34         if(m)
35                 set_manager(m);
36         else if(ARB_direct_state_access)
37                 glCreateTextures(target, 1, &id);
38         else
39                 glGenTextures(1, &id);
40 }
41
42 Texture::~Texture()
43 {
44         while(TexUnit *unit = TexUnit::find_unit(this))
45                 unbind_from(unit->get_index());
46
47         if(id)
48                 glDeleteTextures(1, &id);
49 }
50
51 void Texture::set_format(PixelFormat fmt)
52 {
53         PixelComponents comp = get_components(fmt);
54         PixelComponents st_comp = comp;
55         FormatSwizzle swiz = NO_SWIZZLE;
56         switch(comp)
57         {
58         case LUMINANCE:
59                 st_comp = RED;
60                 swiz = R_TO_LUMINANCE;
61                 break;
62         case LUMINANCE_ALPHA:
63                 st_comp = RG;
64                 swiz = RG_TO_LUMINANCE_ALPHA;
65                 break;
66         case BGR:
67                 st_comp = RGB;
68                 swiz = RGB_TO_BGR;
69                 break;
70         case BGRA:
71                 st_comp = RGBA;
72                 swiz = RGB_TO_BGR;
73                 break;
74         default:;
75         }
76
77         PixelFormat st_fmt = make_pixelformat(st_comp, get_component_type(fmt));
78         require_pixelformat(st_fmt);
79         if(swiz!=NO_SWIZZLE)
80                 static Require _req(ARB_texture_swizzle);
81
82         format = fmt;
83         storage_fmt = st_fmt;
84         swizzle = swiz;
85 }
86
87 void Texture::apply_swizzle()
88 {
89         if(swizzle==NO_SWIZZLE)
90                 return;
91
92         if(get_gl_api()==OPENGL_ES2)
93         {
94                 set_parameter_i(GL_TEXTURE_SWIZZLE_R, swizzle_orders[swizzle*4]);
95                 set_parameter_i(GL_TEXTURE_SWIZZLE_G, swizzle_orders[swizzle*4+1]);
96                 set_parameter_i(GL_TEXTURE_SWIZZLE_B, swizzle_orders[swizzle*4+2]);
97                 set_parameter_i(GL_TEXTURE_SWIZZLE_A, swizzle_orders[swizzle*4+3]);
98         }
99         else
100         {
101                 if(ARB_direct_state_access)
102                         glTextureParameteriv(id, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
103                 else
104                         glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
105         }
106 }
107
108 void Texture::set_parameter_i(GLenum param, int value) const
109 {
110         if(ARB_direct_state_access)
111                 glTextureParameteri(id, param, value);
112         else
113                 glTexParameteri(target, param, value);
114 }
115
116 void Texture::set_min_filter(TextureFilter f)
117 {
118         default_sampler.set_min_filter(f);
119 }
120
121 void Texture::set_mag_filter(TextureFilter f)
122 {
123         default_sampler.set_mag_filter(f);
124 }
125
126 void Texture::set_filter(TextureFilter f)
127 {
128         default_sampler.set_filter(f);
129 }
130
131 void Texture::set_max_anisotropy(float a)
132 {
133         default_sampler.set_max_anisotropy(a);
134 }
135
136 void Texture::set_wrap(TextureWrap w)
137 {
138         default_sampler.set_wrap(w);
139 }
140
141 void Texture::set_wrap_s(TextureWrap w)
142 {
143         default_sampler.set_wrap_s(w);
144 }
145
146 void Texture::set_wrap_t(TextureWrap w)
147 {
148         default_sampler.set_wrap_t(w);
149 }
150
151 void Texture::set_wrap_r(TextureWrap w)
152 {
153         default_sampler.set_wrap_r(w);
154 }
155
156 bool Texture::can_generate_mipmap()
157 {
158         return EXT_framebuffer_object;
159 }
160
161 void Texture::generate_mipmap()
162 {
163         // glGenerateMipmap is defined here
164         static Require _req(EXT_framebuffer_object);
165
166         if(ARB_direct_state_access)
167                 glGenerateTextureMipmap(id);
168         else
169         {
170                 BindRestore _bind(this);
171                 glGenerateMipmap(target);
172         }
173 }
174
175 void Texture::set_auto_generate_mipmap(bool gm)
176 {
177         if(gm)
178                 static Require _req(EXT_framebuffer_object);
179
180         auto_gen_mipmap = gm;
181 }
182
183 void Texture::set_compare_enabled(bool c)
184 {
185         if(c)
186                 default_sampler.set_compare(default_sampler.get_compare_function());
187         else
188                 default_sampler.disable_compare();
189 }
190
191 void Texture::set_compare_func(Predicate f)
192 {
193         default_sampler.set_compare(f);
194 }
195
196 void Texture::load_image(const string &fn, bool)
197 {
198         load_image(fn, 0U);
199 }
200
201 void Texture::load_image(const string &fn, unsigned lv)
202 {
203         Graphics::Image img;
204         img.load_file(fn);
205
206         image(img, lv);
207 }
208
209 void Texture::image(const Graphics::Image &img, bool)
210 {
211         image(img, 0U);
212 }
213
214 void Texture::bind_to(unsigned i) const
215 {
216         if(!id)
217         {
218                 if(manager)
219                         manager->resource_used(*this);
220                 if(!id)
221                 {
222                         unbind_from(i);
223                         return;
224                 }
225         }
226
227         TexUnit &unit = TexUnit::get_unit(i);
228         if(unit.set_texture(this))
229         {
230                 if(manager)
231                         manager->resource_used(*this);
232
233                 if(ARB_direct_state_access)
234                         glBindTextureUnit(i, id);
235                 else
236                 {
237                         unit.bind();
238                         glBindTexture(target, id);
239                 }
240
241                 default_sampler.bind_to(i);
242         }
243 }
244
245 const Texture *Texture::current(unsigned i)
246 {
247         return TexUnit::get_unit(i).get_texture();
248 }
249
250 void Texture::unbind_from(unsigned i)
251 {
252         TexUnit &unit = TexUnit::get_unit(i);
253         const Texture *cur = unit.get_texture();
254         if(unit.set_texture(0))
255         {
256                 if(ARB_direct_state_access)
257                         glBindTextureUnit(i, 0);
258                 else
259                 {
260                         unit.bind();
261                         glBindTexture(cur->target, 0);
262                 }
263         }
264 }
265
266
267 Texture::Loader::Loader(Texture &t):
268         DataFile::CollectionObjectLoader<Texture>(t, 0)
269 {
270         init();
271 }
272
273 Texture::Loader::Loader(Texture &t, Collection &c):
274         DataFile::CollectionObjectLoader<Texture>(t, &c)
275 {
276         init();
277 }
278
279 void Texture::Loader::init()
280 {
281         levels = 0;
282
283         add("external_image", &Loader::external_image);
284         add("external_image_srgb", &Loader::external_image);
285         add("filter", &Loader::filter);
286         add("generate_mipmap", &Loader::generate_mipmap);
287         add("image_data", &Loader::image_data);
288         add("mag_filter", &Loader::mag_filter);
289         add("max_anisotropy", &Loader::max_anisotropy);
290         add("min_filter", &Loader::min_filter);
291         add("mipmap_levels", &Loader::mipmap_levels);
292         add("sampler",    &Loader::sampler);
293         add("wrap",       &Loader::wrap);
294         add("wrap_r",     &Loader::wrap_r);
295         add("wrap_s",     &Loader::wrap_s);
296         add("wrap_t",     &Loader::wrap_t);
297 }
298
299 unsigned Texture::Loader::get_levels() const
300 {
301         return (is_mipmapped(obj.default_sampler.get_min_filter()) ? levels : 1);
302 }
303
304 #pragma GCC diagnostic push
305 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
306 void Texture::Loader::load_external_image(Graphics::Image &img, const std::string &fn)
307 {
308         RefPtr<IO::Seekable> io = get_collection().open_raw(fn);
309         if(!io)
310                 throw IO::file_not_found(fn);
311         img.load_io(*io);
312 }
313
314 void Texture::Loader::external_image(const string &fn)
315 {
316         obj.use_srgb_format = false;
317         external_image_common(fn);
318 }
319
320 void Texture::Loader::external_image_srgb(const string &fn)
321 {
322         obj.use_srgb_format = true;
323         external_image_common(fn);
324 }
325
326 void Texture::Loader::external_image_common(const string &fn)
327 {
328         if(obj.manager)
329                 obj.manager->set_resource_location(obj, get_collection(), fn);
330         else
331         {
332                 Graphics::Image img;
333                 load_external_image(img, fn);
334                 obj.image(img, get_levels());
335         }
336 }
337
338 void Texture::Loader::filter(TextureFilter f)
339 {
340         obj.set_filter(f);
341 }
342
343 void Texture::Loader::generate_mipmap(bool gm)
344 {
345         obj.set_auto_generate_mipmap(gm);
346 }
347
348 void Texture::Loader::image_data(const string &data)
349 {
350         Graphics::Image img;
351         IO::Memory mem(data.data(), data.size());
352         img.load_io(mem);
353
354         obj.image(img, get_levels());
355 }
356
357 void Texture::Loader::mag_filter(TextureFilter f)
358 {
359         obj.set_mag_filter(f);
360 }
361
362 void Texture::Loader::max_anisotropy(float a)
363 {
364         obj.set_max_anisotropy(a);
365 }
366
367 void Texture::Loader::min_filter(TextureFilter f)
368 {
369         obj.set_min_filter(f);
370 }
371
372 void Texture::Loader::mipmap_levels(unsigned l)
373 {
374         levels = l;
375 }
376
377 void Texture::Loader::sampler()
378 {
379         load_sub(obj.default_sampler);
380 }
381
382 void Texture::Loader::wrap(TextureWrap w)
383 {
384         obj.set_wrap(w);
385 }
386
387 void Texture::Loader::wrap_r(TextureWrap w)
388 {
389         obj.set_wrap_r(w);
390 }
391
392 void Texture::Loader::wrap_s(TextureWrap w)
393 {
394         obj.set_wrap_s(w);
395 }
396
397 void Texture::Loader::wrap_t(TextureWrap w)
398 {
399         obj.set_wrap_t(w);
400 }
401 #pragma GCC diagnostic pop
402
403 } // namespace GL
404 } // namespace Msp