]> git.tdb.fi Git - libs/gl.git/blob - source/core/texture.cpp
Remove default sampler from Texture
[libs/gl.git] / source / core / 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/gl/extensions/khr_debug.h>
5 #include <msp/io/memory.h>
6 #include "bindable.h"
7 #include "error.h"
8 #include "resourcemanager.h"
9 #include "resources.h"
10 #include "texture.h"
11 #include "texunit.h"
12
13 using namespace std;
14
15 namespace Msp {
16 namespace GL {
17
18 int Texture::swizzle_orders[] =
19 {
20         GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA,
21         GL_RED, GL_RED, GL_RED, GL_ONE,
22         GL_RED, GL_RED, GL_RED, GL_GREEN,
23         GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA
24 };
25
26 Texture::Texture(GLenum t, ResourceManager *m):
27         id(0),
28         target(t),
29         format(RGB8),
30         storage_fmt(RGB8),
31         swizzle(NO_SWIZZLE),
32         use_srgb_format(false),
33         auto_gen_mipmap(false)
34 {
35         if(m)
36                 set_manager(m);
37         else
38                 generate_id();
39 }
40
41 Texture::~Texture()
42 {
43         while(TexUnit *unit = TexUnit::find_unit(this))
44                 unbind_from(unit->get_index());
45
46         if(id)
47                 glDeleteTextures(1, &id);
48 }
49
50 void Texture::generate_id()
51 {
52         if(id)
53                 throw invalid_operation("Texture::generate_id");
54         if(ARB_direct_state_access)
55                 glCreateTextures(target, 1, &id);
56         else
57                 glGenTextures(1, &id);
58
59 #ifdef DEBUG
60         if(!debug_name.empty() && KHR_debug)
61                 glObjectLabel(GL_TEXTURE, id, debug_name.size(), debug_name.c_str());
62 #endif
63 }
64
65 void Texture::set_format(PixelFormat fmt)
66 {
67         PixelComponents comp = get_components(fmt);
68         PixelComponents st_comp = comp;
69         FormatSwizzle swiz = NO_SWIZZLE;
70         switch(comp)
71         {
72         case LUMINANCE:
73                 st_comp = RED;
74                 swiz = R_TO_LUMINANCE;
75                 break;
76         case LUMINANCE_ALPHA:
77                 st_comp = RG;
78                 swiz = RG_TO_LUMINANCE_ALPHA;
79                 break;
80         case BGR:
81                 st_comp = RGB;
82                 swiz = RGB_TO_BGR;
83                 break;
84         case BGRA:
85                 st_comp = RGBA;
86                 swiz = RGB_TO_BGR;
87                 break;
88         default:;
89         }
90
91         PixelFormat st_fmt = make_pixelformat(st_comp, get_component_type(fmt), is_srgb(fmt));
92         require_pixelformat(st_fmt);
93         if(swiz!=NO_SWIZZLE)
94                 static Require _req(ARB_texture_swizzle);
95
96         format = fmt;
97         storage_fmt = st_fmt;
98         swizzle = swiz;
99 }
100
101 void Texture::apply_swizzle()
102 {
103         if(swizzle==NO_SWIZZLE)
104                 return;
105
106         if(get_gl_api()==OPENGL_ES2)
107         {
108                 set_parameter_i(GL_TEXTURE_SWIZZLE_R, swizzle_orders[swizzle*4]);
109                 set_parameter_i(GL_TEXTURE_SWIZZLE_G, swizzle_orders[swizzle*4+1]);
110                 set_parameter_i(GL_TEXTURE_SWIZZLE_B, swizzle_orders[swizzle*4+2]);
111                 set_parameter_i(GL_TEXTURE_SWIZZLE_A, swizzle_orders[swizzle*4+3]);
112         }
113         else
114         {
115                 if(ARB_direct_state_access)
116                         glTextureParameteriv(id, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
117                 else
118                         glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
119         }
120 }
121
122 void Texture::set_parameter_i(GLenum param, int value) const
123 {
124         if(ARB_direct_state_access)
125                 glTextureParameteri(id, param, value);
126         else
127                 glTexParameteri(target, param, value);
128 }
129
130 bool Texture::can_generate_mipmap()
131 {
132         return EXT_framebuffer_object;
133 }
134
135 void Texture::generate_mipmap()
136 {
137         // glGenerateMipmap is defined here
138         static Require _req(EXT_framebuffer_object);
139
140         if(ARB_direct_state_access)
141                 glGenerateTextureMipmap(id);
142         else
143         {
144                 BindRestore _bind(this);
145                 glGenerateMipmap(target);
146         }
147 }
148
149 void Texture::set_auto_generate_mipmap(bool gm)
150 {
151         if(gm)
152                 static Require _req(EXT_framebuffer_object);
153
154         auto_gen_mipmap = gm;
155 }
156
157 void Texture::load_image(const string &fn, bool)
158 {
159         load_image(fn, 0U);
160 }
161
162 void Texture::load_image(const string &fn, unsigned lv)
163 {
164         Graphics::Image img;
165         img.load_file(fn);
166
167         image(img, lv);
168 }
169
170 void Texture::image(const Graphics::Image &img, bool)
171 {
172         image(img, 0U);
173 }
174
175 void Texture::bind_to(unsigned i) const
176 {
177         if(!id)
178         {
179                 if(manager)
180                         manager->resource_used(*this);
181                 if(!id)
182                 {
183                         unbind_from(i);
184                         return;
185                 }
186         }
187
188         TexUnit &unit = TexUnit::get_unit(i);
189         if(unit.set_texture(this))
190         {
191                 if(manager)
192                         manager->resource_used(*this);
193
194                 if(ARB_direct_state_access)
195                         glBindTextureUnit(i, id);
196                 else
197                 {
198                         unit.bind();
199                         glBindTexture(target, id);
200                 }
201         }
202 }
203
204 const Texture *Texture::current(unsigned i)
205 {
206         return TexUnit::get_unit(i).get_texture();
207 }
208
209 void Texture::unbind_from(unsigned i)
210 {
211         TexUnit &unit = TexUnit::get_unit(i);
212         const Texture *cur = unit.get_texture();
213         if(unit.set_texture(0))
214         {
215                 if(ARB_direct_state_access)
216                         glBindTextureUnit(i, 0);
217                 else
218                 {
219                         unit.bind();
220                         glBindTexture(cur->target, 0);
221                 }
222         }
223 }
224
225 void Texture::set_debug_name(const string &name)
226 {
227 #ifdef DEBUG
228         debug_name = name;
229         if(id && KHR_debug)
230                 glObjectLabel(GL_TEXTURE, id, name.size(), name.c_str());
231 #else
232         (void)name;
233 #endif
234 }
235
236
237 Texture::Loader::Loader(Texture &t):
238         DataFile::CollectionObjectLoader<Texture>(t, 0)
239 {
240         init();
241 }
242
243 Texture::Loader::Loader(Texture &t, Collection &c):
244         DataFile::CollectionObjectLoader<Texture>(t, &c)
245 {
246         init();
247 }
248
249 void Texture::Loader::init()
250 {
251         levels = 0;
252
253         add("external_image", &Loader::external_image);
254         add("external_image_srgb", &Loader::external_image_srgb);
255         add("generate_mipmap", &Loader::generate_mipmap);
256         add("image_data", &Loader::image_data);
257         add("mipmap_levels", &Loader::mipmap_levels);
258 }
259
260 void Texture::Loader::load_external_image(Graphics::Image &img, const string &fn)
261 {
262         RefPtr<IO::Seekable> io = get_collection().open_raw(fn);
263         if(!io)
264                 throw IO::file_not_found(fn);
265         img.load_io(*io);
266 }
267
268 void Texture::Loader::external_image(const string &fn)
269 {
270         obj.use_srgb_format = false;
271         external_image_common(fn);
272 }
273
274 void Texture::Loader::external_image_srgb(const string &fn)
275 {
276         obj.use_srgb_format = true;
277         external_image_common(fn);
278 }
279
280 void Texture::Loader::external_image_common(const string &fn)
281 {
282         if(obj.manager)
283                 obj.manager->set_resource_location(obj, get_collection(), fn);
284         else
285         {
286                 Graphics::Image img;
287                 load_external_image(img, fn);
288                 obj.image(img, levels);
289         }
290 }
291
292 void Texture::Loader::generate_mipmap(bool gm)
293 {
294         obj.set_auto_generate_mipmap(gm);
295 }
296
297 void Texture::Loader::image_data(const string &data)
298 {
299         if(obj.manager)
300         {
301                 obj.set_manager(0);
302                 if(!obj.id)
303                         obj.generate_id();
304         }
305
306         Graphics::Image img;
307         IO::Memory mem(data.data(), data.size());
308         img.load_io(mem);
309
310         obj.image(img, levels);
311 }
312
313 void Texture::Loader::mipmap_levels(unsigned l)
314 {
315         levels = l;
316 }
317
318 } // namespace GL
319 } // namespace Msp