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