]> git.tdb.fi Git - libs/gl.git/blob - source/core/texture.cpp
Remove the PixelStore class
[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
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         use_srgb_format(false),
32         auto_gen_mipmap(false)
33 {
34         if(m)
35                 set_manager(m);
36         else
37                 generate_id();
38
39         static bool alignment_init = false;
40         if(!alignment_init)
41         {
42                 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
43                 alignment_init = true;
44         }
45 }
46
47 Texture::~Texture()
48 {
49         if(id)
50                 glDeleteTextures(1, &id);
51 }
52
53 void Texture::generate_id()
54 {
55         if(id)
56                 throw invalid_operation("Texture::generate_id");
57         if(ARB_direct_state_access)
58                 glCreateTextures(target, 1, &id);
59         else
60                 glGenTextures(1, &id);
61
62 #ifdef DEBUG
63         if(!debug_name.empty() && KHR_debug)
64                 glObjectLabel(GL_TEXTURE, id, debug_name.size(), debug_name.c_str());
65 #endif
66 }
67
68 void Texture::set_format(PixelFormat fmt)
69 {
70         PixelComponents comp = get_components(fmt);
71         PixelComponents st_comp = comp;
72         FormatSwizzle swiz = NO_SWIZZLE;
73         switch(comp)
74         {
75         case LUMINANCE:
76                 st_comp = RED;
77                 swiz = R_TO_LUMINANCE;
78                 break;
79         case LUMINANCE_ALPHA:
80                 st_comp = RG;
81                 swiz = RG_TO_LUMINANCE_ALPHA;
82                 break;
83         case BGR:
84                 st_comp = RGB;
85                 swiz = RGB_TO_BGR;
86                 break;
87         case BGRA:
88                 st_comp = RGBA;
89                 swiz = RGB_TO_BGR;
90                 break;
91         default:;
92         }
93
94         PixelFormat st_fmt = make_pixelformat(st_comp, get_component_type(fmt), is_srgb(fmt));
95         require_pixelformat(st_fmt);
96         if(swiz!=NO_SWIZZLE)
97                 static Require _req(ARB_texture_swizzle);
98
99         format = fmt;
100         storage_fmt = st_fmt;
101         swizzle = swiz;
102 }
103
104 void Texture::apply_swizzle()
105 {
106         if(swizzle==NO_SWIZZLE)
107                 return;
108
109         if(get_gl_api()==OPENGL_ES2)
110         {
111                 set_parameter_i(GL_TEXTURE_SWIZZLE_R, swizzle_orders[swizzle*4]);
112                 set_parameter_i(GL_TEXTURE_SWIZZLE_G, swizzle_orders[swizzle*4+1]);
113                 set_parameter_i(GL_TEXTURE_SWIZZLE_B, swizzle_orders[swizzle*4+2]);
114                 set_parameter_i(GL_TEXTURE_SWIZZLE_A, swizzle_orders[swizzle*4+3]);
115         }
116         else
117         {
118                 if(ARB_direct_state_access)
119                         glTextureParameteriv(id, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
120                 else
121                         glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
122         }
123 }
124
125 void Texture::set_parameter_i(GLenum param, int value) const
126 {
127         if(ARB_direct_state_access)
128                 glTextureParameteri(id, param, value);
129         else
130                 glTexParameteri(target, param, value);
131 }
132
133 bool Texture::can_generate_mipmap()
134 {
135         return EXT_framebuffer_object;
136 }
137
138 void Texture::generate_mipmap()
139 {
140         // glGenerateMipmap is defined here
141         static Require _req(EXT_framebuffer_object);
142
143         if(!ARB_direct_state_access)
144         {
145                 glActiveTexture(GL_TEXTURE0);
146                 glBindTexture(target, id);
147         }
148         generate_mipmap_();
149         if(!ARB_direct_state_access)
150                 glBindTexture(target, 0);
151 }
152
153 void Texture::generate_mipmap_()
154 {
155         if(ARB_direct_state_access)
156                 glGenerateTextureMipmap(id);
157         else
158                 glGenerateMipmap(target);
159 }
160
161 void Texture::set_auto_generate_mipmap(bool gm)
162 {
163         if(gm)
164                 static Require _req(EXT_framebuffer_object);
165
166         auto_gen_mipmap = gm;
167 }
168
169 void Texture::load_image(const string &fn, bool)
170 {
171         load_image(fn, 0U);
172 }
173
174 void Texture::load_image(const string &fn, unsigned lv)
175 {
176         Graphics::Image img;
177         img.load_file(fn);
178
179         image(img, lv);
180 }
181
182 void Texture::image(const Graphics::Image &img, bool)
183 {
184         image(img, 0U);
185 }
186
187 void Texture::set_debug_name(const string &name)
188 {
189 #ifdef DEBUG
190         debug_name = name;
191         if(id && KHR_debug)
192                 glObjectLabel(GL_TEXTURE, id, name.size(), name.c_str());
193 #else
194         (void)name;
195 #endif
196 }
197
198
199 Texture::Loader::Loader(Texture &t):
200         DataFile::CollectionObjectLoader<Texture>(t, 0)
201 {
202         init();
203 }
204
205 Texture::Loader::Loader(Texture &t, Collection &c):
206         DataFile::CollectionObjectLoader<Texture>(t, &c)
207 {
208         init();
209 }
210
211 void Texture::Loader::init()
212 {
213         levels = 0;
214
215         add("external_image", &Loader::external_image);
216         add("external_image_srgb", &Loader::external_image_srgb);
217         add("generate_mipmap", &Loader::generate_mipmap);
218         add("image_data", &Loader::image_data);
219         add("mipmap_levels", &Loader::mipmap_levels);
220 }
221
222 void Texture::Loader::load_external_image(Graphics::Image &img, const string &fn)
223 {
224         RefPtr<IO::Seekable> io = get_collection().open_raw(fn);
225         if(!io)
226                 throw IO::file_not_found(fn);
227         img.load_io(*io);
228 }
229
230 void Texture::Loader::external_image(const string &fn)
231 {
232         obj.use_srgb_format = false;
233         external_image_common(fn);
234 }
235
236 void Texture::Loader::external_image_srgb(const string &fn)
237 {
238         obj.use_srgb_format = true;
239         external_image_common(fn);
240 }
241
242 void Texture::Loader::external_image_common(const string &fn)
243 {
244         if(obj.manager)
245                 obj.manager->set_resource_location(obj, get_collection(), fn);
246         else
247         {
248                 Graphics::Image img;
249                 load_external_image(img, fn);
250                 obj.image(img, levels);
251         }
252 }
253
254 void Texture::Loader::generate_mipmap(bool gm)
255 {
256         obj.set_auto_generate_mipmap(gm);
257 }
258
259 void Texture::Loader::image_data(const string &data)
260 {
261         if(obj.manager)
262         {
263                 obj.set_manager(0);
264                 if(!obj.id)
265                         obj.generate_id();
266         }
267
268         Graphics::Image img;
269         IO::Memory mem(data.data(), data.size());
270         img.load_io(mem);
271
272         obj.image(img, levels);
273 }
274
275 void Texture::Loader::mipmap_levels(unsigned l)
276 {
277         levels = l;
278 }
279
280 } // namespace GL
281 } // namespace Msp