0029528: Visualization, TKOpenGl - allow defining sRGB textures
[occt.git] / src / OpenGl / OpenGl_TextureFormat.cxx
1 // Copyright (c) 2017-2019 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <OpenGl_TextureFormat.hxx>
15
16 #include <OpenGl_Context.hxx>
17
18 // =======================================================================
19 // function : FindFormat
20 // purpose  :
21 // =======================================================================
22 OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Context)& theCtx,
23                                                        Image_Format theFormat,
24                                                        bool theIsColorMap)
25 {
26   OpenGl_TextureFormat aFormat;
27   switch (theFormat)
28   {
29     case Image_Format_GrayF:
30     {
31       aFormat.SetNbComponents (1);
32       if (theCtx->core11 == NULL)
33       {
34         aFormat.SetInternalFormat (GL_R8); // GL_R32F
35         aFormat.SetPixelFormat (GL_RED);
36       }
37       else
38       {
39       #if !defined(GL_ES_VERSION_2_0)
40         aFormat.SetInternalFormat (GL_LUMINANCE8);
41       #else
42         aFormat.SetInternalFormat (GL_LUMINANCE);
43       #endif
44         aFormat.SetPixelFormat (GL_LUMINANCE);
45       }
46       aFormat.SetDataType (GL_FLOAT);
47       return aFormat;
48     }
49     case Image_Format_AlphaF:
50     {
51       aFormat.SetNbComponents (1);
52       if (theCtx->core11 == NULL)
53       {
54         aFormat.SetInternalFormat (GL_R8);  // GL_R32F
55         aFormat.SetPixelFormat (GL_RED);
56       }
57       else
58       {
59       #if !defined(GL_ES_VERSION_2_0)
60         aFormat.SetInternalFormat (GL_ALPHA8);
61       #else
62         aFormat.SetInternalFormat (GL_ALPHA);
63       #endif
64         aFormat.SetPixelFormat (GL_ALPHA);
65       }
66       aFormat.SetDataType (GL_FLOAT);
67       return aFormat;
68     }
69     case Image_Format_RGBAF:
70     {
71       aFormat.SetNbComponents (4);
72       aFormat.SetInternalFormat (GL_RGBA8); // GL_RGBA32F
73       aFormat.SetPixelFormat (GL_RGBA);
74       aFormat.SetDataType (GL_FLOAT);
75       return aFormat;
76     }
77     case Image_Format_BGRAF:
78     {
79       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
80       {
81         return OpenGl_TextureFormat();
82       }
83       aFormat.SetNbComponents (4);
84       aFormat.SetInternalFormat (GL_RGBA8); // GL_RGBA32F
85       aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
86       aFormat.SetDataType (GL_FLOAT);
87       return aFormat;
88     }
89     case Image_Format_RGBF:
90     {
91       aFormat.SetNbComponents (3);
92       aFormat.SetInternalFormat (GL_RGB8); // GL_RGB32F
93       aFormat.SetPixelFormat (GL_RGB);
94       aFormat.SetDataType (GL_FLOAT);
95       return aFormat;
96     }
97     case Image_Format_BGRF:
98     {
99     #if !defined(GL_ES_VERSION_2_0)
100       aFormat.SetNbComponents (3);
101       aFormat.SetInternalFormat (GL_RGB8); // GL_RGB32F
102       aFormat.SetPixelFormat (GL_BGR);     // equals to GL_BGR_EXT
103       aFormat.SetDataType (GL_FLOAT);
104       return aFormat;
105     #else
106       return OpenGl_TextureFormat();
107     #endif
108     }
109     case Image_Format_RGBA:
110     {
111       aFormat.SetNbComponents (4);
112       aFormat.SetInternalFormat (GL_RGBA8);
113       aFormat.SetPixelFormat (GL_RGBA);
114       aFormat.SetDataType (GL_UNSIGNED_BYTE);
115       if (theIsColorMap
116        && theCtx->ToRenderSRGB())
117       {
118         aFormat.SetInternalFormat (GL_SRGB8_ALPHA8);
119       }
120       return aFormat;
121     }
122     case Image_Format_BGRA:
123     {
124     #if !defined(GL_ES_VERSION_2_0)
125       if (!theCtx->IsGlGreaterEqual (1, 2)
126        && !theCtx->extBgra)
127       {
128         return OpenGl_TextureFormat();
129       }
130       aFormat.SetNbComponents (4);
131       aFormat.SetInternalFormat (GL_RGBA8);
132       if (theIsColorMap
133        && theCtx->ToRenderSRGB())
134       {
135         aFormat.SetInternalFormat (GL_SRGB8_ALPHA8);
136       }
137     #else
138       if (theIsColorMap
139        && theCtx->ToRenderSRGB())
140       {
141         // GL_SRGB8_ALPHA8 with texture swizzling would be better
142       }
143       if (!theCtx->extBgra)
144       {
145         return OpenGl_TextureFormat();
146       }
147       aFormat.SetNbComponents (4);
148           aFormat.SetInternalFormat (GL_BGRA_EXT);
149     #endif
150       aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
151       aFormat.SetDataType (GL_UNSIGNED_BYTE);
152       return aFormat;
153     }
154     case Image_Format_RGB32:
155     {
156     #if !defined(GL_ES_VERSION_2_0)
157       // ask driver to convert data to RGB8 to save memory
158       aFormat.SetNbComponents (3);
159       aFormat.SetInternalFormat (GL_RGB8);
160       if (theIsColorMap
161        && theCtx->ToRenderSRGB())
162       {
163         aFormat.SetInternalFormat (GL_SRGB8);
164       }
165     #else
166       // conversion is not supported
167       aFormat.SetNbComponents (4);
168       aFormat.SetInternalFormat (GL_RGBA8);
169       if (theIsColorMap
170        && theCtx->ToRenderSRGB())
171       {
172         aFormat.SetInternalFormat (GL_SRGB8_ALPHA8);
173       }
174     #endif
175       aFormat.SetPixelFormat (GL_RGBA);
176       aFormat.SetDataType (GL_UNSIGNED_BYTE);
177       return aFormat;
178     }
179     case Image_Format_BGR32:
180     {
181     #if !defined(GL_ES_VERSION_2_0)
182       if (!theCtx->IsGlGreaterEqual(1, 2) && !theCtx->extBgra)
183       {
184         return OpenGl_TextureFormat();
185       }
186       aFormat.SetNbComponents (3);
187       aFormat.SetInternalFormat (GL_RGB8);
188       if (theIsColorMap
189        && theCtx->ToRenderSRGB())
190       {
191         aFormat.SetInternalFormat (GL_SRGB8);
192       }
193     #else
194       if (theIsColorMap
195        && theCtx->ToRenderSRGB())
196       {
197         // GL_SRGB8_ALPHA8 with texture swizzling would be better
198       }
199       if (!theCtx->extBgra)
200       {
201         return OpenGl_TextureFormat();
202       }
203       aFormat.SetNbComponents (4);
204       aFormat.SetInternalFormat (GL_BGRA_EXT);
205     #endif
206       aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
207       aFormat.SetDataType (GL_UNSIGNED_BYTE);
208       return aFormat;
209     }
210     case Image_Format_RGB:
211     {
212       aFormat.SetNbComponents (3);
213       aFormat.SetInternalFormat (GL_RGB8);
214       aFormat.SetPixelFormat (GL_RGB);
215       aFormat.SetDataType (GL_UNSIGNED_BYTE);
216       if (theIsColorMap
217        && theCtx->ToRenderSRGB())
218       {
219         aFormat.SetInternalFormat (GL_SRGB8);
220       }
221       return aFormat;
222     }
223     case Image_Format_BGR:
224     {
225     #if !defined(GL_ES_VERSION_2_0)
226       if (!theCtx->IsGlGreaterEqual (1, 2)
227        && !theCtx->extBgra)
228       {
229         return OpenGl_TextureFormat();
230       }
231       aFormat.SetNbComponents (3);
232       aFormat.SetInternalFormat (GL_RGB8);
233       if (theIsColorMap
234        && theCtx->ToRenderSRGB())
235       {
236         aFormat.SetInternalFormat (GL_SRGB8);
237       }
238       aFormat.SetPixelFormat (GL_BGR); // equals to GL_BGR_EXT
239       aFormat.SetDataType (GL_UNSIGNED_BYTE);
240     #endif
241       return aFormat;
242     }
243     case Image_Format_Gray:
244     {
245       aFormat.SetNbComponents (1);
246       if (theCtx->core11 == NULL)
247       {
248         aFormat.SetInternalFormat (GL_R8);
249         aFormat.SetPixelFormat (GL_RED);
250       }
251       else
252       {
253       #if !defined(GL_ES_VERSION_2_0)
254         aFormat.SetInternalFormat (GL_LUMINANCE8);
255       #else
256         aFormat.SetInternalFormat (GL_LUMINANCE);
257       #endif
258         aFormat.SetPixelFormat (GL_LUMINANCE);
259       }
260       aFormat.SetDataType (GL_UNSIGNED_BYTE);
261       return aFormat;
262     }
263     case Image_Format_Alpha:
264     {
265       aFormat.SetNbComponents (1);
266       if (theCtx->core11 == NULL)
267       {
268         aFormat.SetInternalFormat (GL_R8);
269         aFormat.SetPixelFormat (GL_RED);
270       }
271       else
272       {
273       #if !defined(GL_ES_VERSION_2_0)
274         aFormat.SetInternalFormat (GL_ALPHA8);
275       #else
276         aFormat.SetInternalFormat (GL_ALPHA);
277       #endif
278         aFormat.SetPixelFormat (GL_ALPHA);
279       }
280       aFormat.SetDataType (GL_UNSIGNED_BYTE);
281       return aFormat;
282     }
283     case Image_Format_UNKNOWN:
284     {
285       return OpenGl_TextureFormat();
286     }
287   }
288   return OpenGl_TextureFormat();
289 }
290
291 // =======================================================================
292 // function : FindSizedFormat
293 // purpose  :
294 // =======================================================================
295 OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_Context)& theCtx,
296                                                             GLint theSizedFormat)
297 {
298   OpenGl_TextureFormat aFormat;
299   switch (theSizedFormat)
300   {
301     case GL_RGBA32F:
302     {
303       aFormat.SetNbComponents (4);
304       aFormat.SetInternalFormat (theSizedFormat);
305       aFormat.SetPixelFormat (GL_RGBA);
306       aFormat.SetDataType (GL_FLOAT);
307       return aFormat;
308     }
309     case GL_R32F:
310     {
311       aFormat.SetNbComponents (1);
312       aFormat.SetInternalFormat (theSizedFormat);
313       aFormat.SetPixelFormat (GL_RED);
314       aFormat.SetDataType (GL_FLOAT);
315       return aFormat;
316     }
317     case GL_RGBA16F:
318     {
319       aFormat.SetNbComponents (4);
320       aFormat.SetInternalFormat (theSizedFormat);
321       aFormat.SetPixelFormat (GL_RGBA);
322       aFormat.SetDataType (GL_HALF_FLOAT);
323       if (theCtx->hasHalfFloatBuffer == OpenGl_FeatureInExtensions)
324       {
325       #if defined(GL_ES_VERSION_2_0)
326         aFormat.SetDataType (GL_HALF_FLOAT_OES);
327       #else
328         aFormat.SetDataType (GL_FLOAT);
329       #endif
330       }
331       return aFormat;
332     }
333     case GL_R16F:
334     {
335       aFormat.SetNbComponents (1);
336       aFormat.SetInternalFormat (theSizedFormat);
337       aFormat.SetPixelFormat (GL_RED);
338       aFormat.SetDataType (GL_HALF_FLOAT);
339       if (theCtx->hasHalfFloatBuffer == OpenGl_FeatureInExtensions)
340       {
341       #if defined(GL_ES_VERSION_2_0)
342         aFormat.SetDataType (GL_HALF_FLOAT_OES);
343       #else
344         aFormat.SetDataType (GL_FLOAT);
345       #endif
346       }
347       return aFormat;
348     }
349     case GL_SRGB8_ALPHA8:
350     case GL_RGBA8:
351     case GL_RGBA:
352     {
353       aFormat.SetNbComponents (4);
354       aFormat.SetInternalFormat (theSizedFormat);
355       aFormat.SetPixelFormat (GL_RGBA);
356       aFormat.SetDataType (GL_UNSIGNED_BYTE);
357       if (theSizedFormat == GL_SRGB8_ALPHA8
358       && !theCtx->ToRenderSRGB())
359       {
360         aFormat.SetInternalFormat (GL_RGBA8); // fallback format
361       }
362       return aFormat;
363     }
364     case GL_SRGB8:
365     case GL_RGB8:
366     case GL_RGB:
367     {
368       aFormat.SetNbComponents (3);
369       aFormat.SetInternalFormat (theSizedFormat);
370       aFormat.SetPixelFormat (GL_RGB);
371       aFormat.SetDataType (GL_UNSIGNED_BYTE);
372       if (theSizedFormat == GL_SRGB8
373       && !theCtx->ToRenderSRGB())
374       {
375         aFormat.SetInternalFormat (GL_RGB8); // fallback format
376       }
377       return aFormat;
378     }
379     // integer types
380     case GL_R32I:
381     {
382       aFormat.SetNbComponents (1);
383       aFormat.SetInternalFormat (theSizedFormat);
384       aFormat.SetPixelFormat (GL_RED_INTEGER);
385       aFormat.SetDataType (GL_INT);
386       return aFormat;
387     }
388     case GL_RG32I:
389     {
390       aFormat.SetNbComponents (2);
391       aFormat.SetInternalFormat (theSizedFormat);
392       aFormat.SetPixelFormat (GL_RG_INTEGER);
393       aFormat.SetDataType (GL_INT);
394       return aFormat;
395     }
396     // depth formats
397     case GL_DEPTH24_STENCIL8:
398     {
399       aFormat.SetNbComponents (2);
400       aFormat.SetInternalFormat (theSizedFormat);
401       aFormat.SetPixelFormat (GL_DEPTH_STENCIL);
402       aFormat.SetDataType (GL_UNSIGNED_INT_24_8);
403       return aFormat;
404     }
405     case GL_DEPTH32F_STENCIL8:
406     {
407       aFormat.SetNbComponents (2);
408       aFormat.SetInternalFormat (theSizedFormat);
409       aFormat.SetPixelFormat (GL_DEPTH_STENCIL);
410       aFormat.SetDataType (GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
411       return aFormat;
412     }
413     case GL_DEPTH_COMPONENT16:
414     {
415       aFormat.SetNbComponents (1);
416       aFormat.SetInternalFormat (theSizedFormat);
417       aFormat.SetPixelFormat (GL_DEPTH_COMPONENT);
418       aFormat.SetDataType (GL_UNSIGNED_SHORT);
419       return aFormat;
420     }
421     case GL_DEPTH_COMPONENT24:
422     {
423       aFormat.SetNbComponents (1);
424       aFormat.SetInternalFormat (theSizedFormat);
425       aFormat.SetPixelFormat (GL_DEPTH_COMPONENT);
426       aFormat.SetDataType (GL_UNSIGNED_INT);
427       return aFormat;
428     }
429     case GL_DEPTH_COMPONENT32F:
430     {
431       aFormat.SetNbComponents (1);
432       aFormat.SetInternalFormat (theSizedFormat);
433       aFormat.SetPixelFormat (GL_DEPTH_COMPONENT);
434       aFormat.SetDataType (GL_FLOAT);
435       return aFormat;
436     }
437   }
438   return aFormat;
439 }