]> git.tdb.fi Git - libs/gl.git/blob - source/pixelformat.cpp
Make ambient occlusion edge detection threshold adjustable
[libs/gl.git] / source / pixelformat.cpp
1 #include <msp/gl/extensions/arb_texture_float.h>
2 #include <msp/gl/extensions/ext_bgra.h>
3 #include <msp/strings/format.h>
4 #include "pixelformat.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 void operator>>(const LexicalConverter &conv, PixelFormat &fmt)
12 {
13         if(conv.get()=="STENCIL_INDEX")
14                 fmt = STENCIL_INDEX;
15         else if(conv.get()=="DEPTH_COMPONENT")
16                 fmt = DEPTH_COMPONENT;
17         else if(conv.get()=="RED")
18                 fmt = RED;
19         else if(conv.get()=="RG")
20                 fmt = RG;
21         else if(conv.get()=="RGB")
22                 fmt = RGB;
23         else if(conv.get()=="RGBA")
24                 fmt = RGBA;
25         else if(conv.get()=="BGR")
26                 fmt = BGR;
27         else if(conv.get()=="BGRA")
28                 fmt = BGRA;
29         else if(conv.get()=="SRGB")
30                 fmt = SRGB;
31         else if(conv.get()=="SRGB_ALPHA")
32                 fmt = SRGB_ALPHA;
33         else if(conv.get()=="LUMINANCE")
34                 fmt = LUMINANCE;
35         else if(conv.get()=="LUMINANCE_ALPHA")
36                 fmt = LUMINANCE_ALPHA;
37         else if(conv.get()=="SLUMINANCE")
38                 fmt = SLUMINANCE;
39         else if(conv.get()=="SLUMINANCE_ALPHA")
40                 fmt = SLUMINANCE_ALPHA;
41         else
42                 throw lexical_error(format("conversion of '%s' to PixelFormat", conv.get()));
43 }
44
45 PixelFormat pixelformat_from_graphics(Graphics::PixelFormat pf)
46 {
47         switch(pf)
48         {
49         case Graphics::LUMINANCE: return LUMINANCE;
50         case Graphics::LUMINANCE_ALPHA: return LUMINANCE_ALPHA;
51         case Graphics::RGB: return RGB;
52         case Graphics::RGBX:
53         case Graphics::RGBA: return RGBA;
54         case Graphics::BGR: return BGR;
55         case Graphics::BGRX:
56         case Graphics::BGRA: return BGRA;
57         default: throw invalid_argument("pixelformat_from_graphics");
58         }
59 }
60
61 PixelFormat storage_pixelformat_from_graphics(Graphics::PixelFormat pf, bool srgb)
62 {
63         PixelFormat result;
64         switch(pf)
65         {
66         case Graphics::RGBX:
67         case Graphics::BGR:
68         case Graphics::BGRX: result = RGB; break;
69         case Graphics::BGRA: result = RGBA; break;
70         default: result = pixelformat_from_graphics(pf);
71         }
72
73         if(srgb)
74                 return get_srgb_pixelformat(result);
75         else
76                 return result;
77 }
78
79 PixelFormat get_base_pixelformat(PixelFormat pf)
80 {
81         PixelFormat unsized = get_unsized_pixelformat(pf);
82         switch(unsized)
83         {
84         case SRGB: return RGB;
85         case SRGB_ALPHA: return RGBA;
86         case SLUMINANCE: return LUMINANCE;
87         case SLUMINANCE_ALPHA: return LUMINANCE_ALPHA;
88         default: return unsized;
89         }
90 }
91
92 PixelFormat get_unsized_pixelformat(PixelFormat pf)
93 {
94         switch(pf)
95         {
96         case R8:
97         case R16F:
98         case R32F: return RED;
99         case RG8:
100         case RG16F:
101         case RG32F: return RG;
102         case RGB8:
103         case RGB16F:
104         case RGB32F: return RGB;
105         case SRGB8: return SRGB;
106         case RGBA8:
107         case RGBA16F:
108         case RGBA32F: return RGBA;
109         case SRGB8_ALPHA8: return SRGB_ALPHA;
110         case LUMINANCE8: return LUMINANCE;
111         case SLUMINANCE8: return SLUMINANCE;
112         case LUMINANCE_ALPHA8: return LUMINANCE_ALPHA;
113         case SLUMINANCE8_ALPHA8: return SLUMINANCE_ALPHA;
114         case DEPTH_COMPONENT16:
115         case DEPTH_COMPONENT24:
116         case DEPTH_COMPONENT32:
117         case DEPTH_COMPONENT32F: return DEPTH_COMPONENT;
118         default: return pf;
119         }
120 }
121
122 PixelFormat get_sized_pixelformat(PixelFormat pf, unsigned size)
123 {
124         if(!size || size>4)
125                 throw invalid_argument("get_sized_pixelformat");
126
127         pf = get_unsized_pixelformat(pf);
128
129         switch(size)
130         {
131         case 1:
132                 switch(pf)
133                 {
134                 case RED: return R8;
135                 case RG: return RG8;
136                 case RGB: return RGB8;
137                 case RGBA: return RGBA8;
138                 case SRGB: return SRGB8;
139                 case SRGB_ALPHA: return SRGB8_ALPHA8;
140                 case LUMINANCE: return LUMINANCE8;
141                 case SLUMINANCE: return SLUMINANCE8;
142                 case LUMINANCE_ALPHA: return LUMINANCE8_ALPHA8;
143                 case SLUMINANCE_ALPHA: return SLUMINANCE8_ALPHA8;
144                 default: throw invalid_argument("get_sized_pixelformat");
145                 }
146         case 2:
147                 switch(pf)
148                 {
149                 case RED: return R16F;
150                 case RG: return RG16F;
151                 case RGB: return RGB16F;
152                 case RGBA: return RGBA16F;
153                 case DEPTH_COMPONENT: return DEPTH_COMPONENT16;
154                 default: throw invalid_argument("get_sized_pixelformat");
155                 }
156         case 3:
157                 if(pf==DEPTH_COMPONENT)
158                         return DEPTH_COMPONENT24;
159                 else
160                         throw invalid_argument("get_sized_pixelformat");
161         case 4:
162                 switch(pf)
163                 {
164                 case RED: return R32F;
165                 case RG: return RG32F;
166                 case RGB: return RGB32F;
167                 case RGBA: return RGBA32F;
168                 case DEPTH_COMPONENT: return ARB_depth_buffer_float ? DEPTH_COMPONENT32F : DEPTH_COMPONENT32;
169                 default: throw invalid_argument("get_sized_pixelformat");
170                 }
171         default:
172                 throw invalid_argument("get_sized_pixelformat");
173         }
174 }
175
176 PixelFormat get_default_sized_pixelformat(PixelFormat pf)
177 {
178         pf = get_unsized_pixelformat(pf);
179         unsigned size = 1;
180         if(pf==DEPTH_COMPONENT)
181         {
182                 if(get_gl_api()==OPENGL_ES2 && !ARB_depth_buffer_float)
183                         size = 2;
184                 else
185                         size = 4;
186         }
187         return get_sized_pixelformat(pf, size);
188 }
189
190 PixelFormat get_srgb_pixelformat(PixelFormat pf)
191 {
192         switch(pf)
193         {
194         case RGB: return SRGB;
195         case RGBA: return SRGB_ALPHA;
196         case RGB8: return SRGB8;
197         case RGBA8: return SRGB8_ALPHA8;
198         case LUMINANCE: return SLUMINANCE;
199         case LUMINANCE8: return SLUMINANCE8;
200         case LUMINANCE_ALPHA: return SLUMINANCE_ALPHA;
201         case LUMINANCE_ALPHA8: return SLUMINANCE8_ALPHA8;
202         default: return pf;
203         }
204 }
205
206 unsigned get_component_count(PixelFormat pf)
207 {
208         switch(get_base_pixelformat(pf))
209         {
210         case STENCIL_INDEX:
211         case DEPTH_COMPONENT:
212         case RED:
213         case LUMINANCE:
214         case SLUMINANCE:
215                 return 1;
216         case RG:
217         case LUMINANCE_ALPHA:
218         case SLUMINANCE_ALPHA:
219                 return 2;
220         case RGB:
221         case BGR:
222                 return 3;
223         case RGBA:
224         case BGRA:
225                 return 4;
226         default:
227                 throw invalid_argument("get_component_count");
228         }
229 }
230
231 unsigned get_component_size(PixelFormat pf)
232 {
233         switch(pf)
234         {
235         case R8:
236         case RG8:
237         case RGB8:
238         case RGBA8:
239         case SRGB8:
240         case SRGB8_ALPHA8:
241         case LUMINANCE8:
242         case LUMINANCE8_ALPHA8:
243         case SLUMINANCE8:
244         case SLUMINANCE8_ALPHA8:
245                 return 1;
246         case R16F:
247         case RG16F:
248         case RGB16F:
249         case RGBA16F:
250         case DEPTH_COMPONENT16:
251                 return 2;
252         case DEPTH_COMPONENT24:
253                 return 3;
254         case R32F:
255         case RG32F:
256         case RGB32F:
257         case RGBA32F:
258         case DEPTH_COMPONENT32:
259         case DEPTH_COMPONENT32F:
260                 return 4;
261         default:
262                 return 0;
263         }
264 }
265
266 unsigned get_pixel_size(PixelFormat pf)
267 {
268         return get_component_count(pf)*max(get_component_size(pf), 1U);
269 }
270
271 void require_pixelformat(PixelFormat pf)
272 {
273         /* TODO These checks are only accurate for textures.  On OpenGL ES some
274         formats are allowed for render buffers earlier than textures.  In particular
275         it's possible to create a 16-bit depth renderbuffer on OpenGL ES 2.0 but
276         depth textures are only available with 3.0 or the OES_depth_texture
277         extension.*/
278         switch(pf)
279         {
280         case RGB8:
281         case RGBA8:
282                 { static Require _req(OES_required_internalformat); }
283                 break;
284         case RED:
285         case R8:
286         case RG:
287         case RG8:
288                 { static Require _req(ARB_texture_rg); }
289                 break;
290         case R16F:
291         case R32F:
292         case RG16F:
293         case RG32F:
294                 { static Require _req(ARB_texture_rg); }
295                 { static Require _req(ARB_texture_float); }
296                 break;
297         case RGB16F:
298         case RGB32F:
299         case RGBA16F:
300         case RGBA32F:
301                 { static Require _req(ARB_texture_float); }
302                 break;
303         case SRGB:
304         case SRGB8:
305         case SRGB_ALPHA:
306         case SRGB8_ALPHA8:
307         case SLUMINANCE:
308         case SLUMINANCE8:
309         case SLUMINANCE_ALPHA:
310         case SLUMINANCE8_ALPHA8:
311                 { static Require _req(EXT_texture_sRGB); }
312                 break;
313         case BGR:
314         case BGRA:
315                 { static Require _req(EXT_bgra); }
316                 break;
317         case DEPTH_COMPONENT:
318                 { static Require _req(ARB_depth_texture); }
319                 break;
320         case DEPTH_COMPONENT16:
321         case DEPTH_COMPONENT24:
322         case DEPTH_COMPONENT32:
323                 { static Require _req(ARB_depth_texture); }
324                 { static Require _req(OES_required_internalformat); }
325                 break;
326         case DEPTH_COMPONENT32F:
327                 { static Require _req(ARB_depth_buffer_float); }
328                 break;
329         case STENCIL_INDEX:
330                 { static Require _req(OES_texture_stencil8); }
331                 break;
332         default:
333                 break;
334         }
335 }
336
337 } // namespace GL
338 } // namespace Msp