0031478: Visualization, TKOpenGl - allow uploading Cubemap in compressed DDS format...
[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 <Image_SupportedFormats.hxx>
17 #include <OpenGl_Context.hxx>
18
19 // =======================================================================
20 // function : FindFormat
21 // purpose  :
22 // =======================================================================
23 OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Context)& theCtx,
24                                                        Image_Format theFormat,
25                                                        bool theIsColorMap)
26 {
27   OpenGl_TextureFormat aFormat;
28   switch (theFormat)
29   {
30     case Image_Format_GrayF:
31     {
32       aFormat.SetNbComponents (1);
33       if (theCtx->core11 == NULL)
34       {
35         aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_R32F : GL_R8);
36         aFormat.SetPixelFormat (GL_RED);
37       }
38       else
39       {
40       #if !defined(GL_ES_VERSION_2_0)
41         aFormat.SetInternalFormat (GL_LUMINANCE8);
42       #else
43         aFormat.SetInternalFormat (GL_LUMINANCE);
44       #endif
45         aFormat.SetPixelFormat (GL_LUMINANCE);
46       }
47       aFormat.SetDataType (GL_FLOAT);
48       return aFormat;
49     }
50     case Image_Format_AlphaF:
51     {
52       aFormat.SetNbComponents (1);
53       if (theCtx->core11 == NULL)
54       {
55         aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_R32F : GL_R8);
56         aFormat.SetPixelFormat (GL_RED);
57       }
58       else
59       {
60       #if !defined(GL_ES_VERSION_2_0)
61         aFormat.SetInternalFormat (GL_ALPHA8);
62       #else
63         aFormat.SetInternalFormat (GL_ALPHA);
64       #endif
65         aFormat.SetPixelFormat (GL_ALPHA);
66       }
67       aFormat.SetDataType (GL_FLOAT);
68       return aFormat;
69     }
70     case Image_Format_RGF:
71     {
72       if (!theCtx->arbTexRG)
73       {
74         return OpenGl_TextureFormat();
75       }
76       aFormat.SetNbComponents (2);
77       aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RG32F : GL_RG8);
78       aFormat.SetPixelFormat (GL_RG);
79       aFormat.SetDataType (GL_FLOAT);
80       return aFormat;
81     }
82     case Image_Format_RGBAF:
83     {
84       aFormat.SetNbComponents (4);
85       aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGBA32F : GL_RGBA8);
86       aFormat.SetPixelFormat (GL_RGBA);
87       aFormat.SetDataType (GL_FLOAT);
88       return aFormat;
89     }
90     case Image_Format_BGRAF:
91     {
92       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
93       {
94         return OpenGl_TextureFormat();
95       }
96       aFormat.SetNbComponents (4);
97       aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGBA32F : GL_RGBA8);
98       aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
99       aFormat.SetDataType (GL_FLOAT);
100       return aFormat;
101     }
102     case Image_Format_RGBF:
103     {
104       aFormat.SetNbComponents (3);
105       aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGB32F : GL_RGB8);
106       aFormat.SetPixelFormat (GL_RGB);
107       aFormat.SetDataType (GL_FLOAT);
108       return aFormat;
109     }
110     case Image_Format_BGRF:
111     {
112     #if !defined(GL_ES_VERSION_2_0)
113       aFormat.SetNbComponents (3);
114       aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGB32F : GL_RGB8);
115       aFormat.SetPixelFormat (GL_BGR);     // equals to GL_BGR_EXT
116       aFormat.SetDataType (GL_FLOAT);
117       return aFormat;
118     #else
119       return OpenGl_TextureFormat();
120     #endif
121     }
122     case Image_Format_RGBA:
123     {
124       aFormat.SetNbComponents (4);
125       aFormat.SetInternalFormat (GL_RGBA8);
126       aFormat.SetPixelFormat (GL_RGBA);
127       aFormat.SetDataType (GL_UNSIGNED_BYTE);
128       if (theIsColorMap
129        && theCtx->ToRenderSRGB())
130       {
131         aFormat.SetInternalFormat (GL_SRGB8_ALPHA8);
132       }
133       return aFormat;
134     }
135     case Image_Format_BGRA:
136     {
137     #if !defined(GL_ES_VERSION_2_0)
138       if (!theCtx->IsGlGreaterEqual (1, 2)
139        && !theCtx->extBgra)
140       {
141         return OpenGl_TextureFormat();
142       }
143       aFormat.SetNbComponents (4);
144       aFormat.SetInternalFormat (GL_RGBA8);
145       if (theIsColorMap
146        && theCtx->ToRenderSRGB())
147       {
148         aFormat.SetInternalFormat (GL_SRGB8_ALPHA8);
149       }
150     #else
151       if (theIsColorMap
152        && theCtx->ToRenderSRGB())
153       {
154         // GL_SRGB8_ALPHA8 with texture swizzling would be better
155       }
156       if (!theCtx->extBgra)
157       {
158         return OpenGl_TextureFormat();
159       }
160       aFormat.SetNbComponents (4);
161       aFormat.SetInternalFormat (GL_BGRA_EXT);
162     #endif
163       aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
164       aFormat.SetDataType (GL_UNSIGNED_BYTE);
165       return aFormat;
166     }
167     case Image_Format_RGB32:
168     {
169     #if !defined(GL_ES_VERSION_2_0)
170       // ask driver to convert data to RGB8 to save memory
171       aFormat.SetNbComponents (3);
172       aFormat.SetInternalFormat (GL_RGB8);
173       if (theIsColorMap
174        && theCtx->ToRenderSRGB())
175       {
176         aFormat.SetInternalFormat (GL_SRGB8);
177       }
178     #else
179       // conversion is not supported
180       aFormat.SetNbComponents (4);
181       aFormat.SetInternalFormat (GL_RGBA8);
182       if (theIsColorMap
183        && theCtx->ToRenderSRGB())
184       {
185         aFormat.SetInternalFormat (GL_SRGB8_ALPHA8);
186       }
187     #endif
188       aFormat.SetPixelFormat (GL_RGBA);
189       aFormat.SetDataType (GL_UNSIGNED_BYTE);
190       return aFormat;
191     }
192     case Image_Format_BGR32:
193     {
194     #if !defined(GL_ES_VERSION_2_0)
195       if (!theCtx->IsGlGreaterEqual(1, 2) && !theCtx->extBgra)
196       {
197         return OpenGl_TextureFormat();
198       }
199       aFormat.SetNbComponents (3);
200       aFormat.SetInternalFormat (GL_RGB8);
201       if (theIsColorMap
202        && theCtx->ToRenderSRGB())
203       {
204         aFormat.SetInternalFormat (GL_SRGB8);
205       }
206     #else
207       if (theIsColorMap
208        && theCtx->ToRenderSRGB())
209       {
210         // GL_SRGB8_ALPHA8 with texture swizzling would be better
211       }
212       if (!theCtx->extBgra)
213       {
214         return OpenGl_TextureFormat();
215       }
216       aFormat.SetNbComponents (4);
217       aFormat.SetInternalFormat (GL_BGRA_EXT);
218     #endif
219       aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
220       aFormat.SetDataType (GL_UNSIGNED_BYTE);
221       return aFormat;
222     }
223     case Image_Format_RGB:
224     {
225       aFormat.SetNbComponents (3);
226       aFormat.SetInternalFormat (GL_RGB8);
227       aFormat.SetPixelFormat (GL_RGB);
228       aFormat.SetDataType (GL_UNSIGNED_BYTE);
229       if (theIsColorMap
230        && theCtx->ToRenderSRGB())
231       {
232         aFormat.SetInternalFormat (GL_SRGB8);
233       }
234       return aFormat;
235     }
236     case Image_Format_BGR:
237     {
238     #if !defined(GL_ES_VERSION_2_0)
239       if (!theCtx->IsGlGreaterEqual (1, 2)
240        && !theCtx->extBgra)
241       {
242         return OpenGl_TextureFormat();
243       }
244       aFormat.SetNbComponents (3);
245       aFormat.SetInternalFormat (GL_RGB8);
246       if (theIsColorMap
247        && theCtx->ToRenderSRGB())
248       {
249         aFormat.SetInternalFormat (GL_SRGB8);
250       }
251       aFormat.SetPixelFormat (GL_BGR); // equals to GL_BGR_EXT
252       aFormat.SetDataType (GL_UNSIGNED_BYTE);
253     #endif
254       return aFormat;
255     }
256     case Image_Format_Gray:
257     {
258       aFormat.SetNbComponents (1);
259       if (theCtx->core11 == NULL)
260       {
261         aFormat.SetInternalFormat (GL_R8);
262         aFormat.SetPixelFormat (GL_RED);
263       }
264       else
265       {
266       #if !defined(GL_ES_VERSION_2_0)
267         aFormat.SetInternalFormat (GL_LUMINANCE8);
268       #else
269         aFormat.SetInternalFormat (GL_LUMINANCE);
270       #endif
271         aFormat.SetPixelFormat (GL_LUMINANCE);
272       }
273       aFormat.SetDataType (GL_UNSIGNED_BYTE);
274       return aFormat;
275     }
276     case Image_Format_Alpha:
277     {
278       aFormat.SetNbComponents (1);
279       if (theCtx->core11 == NULL)
280       {
281         aFormat.SetInternalFormat (GL_R8);
282         aFormat.SetPixelFormat (GL_RED);
283       }
284       else
285       {
286       #if !defined(GL_ES_VERSION_2_0)
287         aFormat.SetInternalFormat (GL_ALPHA8);
288       #else
289         aFormat.SetInternalFormat (GL_ALPHA);
290       #endif
291         aFormat.SetPixelFormat (GL_ALPHA);
292       }
293       aFormat.SetDataType (GL_UNSIGNED_BYTE);
294       return aFormat;
295     }
296     case Image_Format_UNKNOWN:
297     {
298       return OpenGl_TextureFormat();
299     }
300   }
301   return OpenGl_TextureFormat();
302 }
303
304 // =======================================================================
305 // function : FindSizedFormat
306 // purpose  :
307 // =======================================================================
308 OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_Context)& theCtx,
309                                                             GLint theSizedFormat)
310 {
311   OpenGl_TextureFormat aFormat;
312   switch (theSizedFormat)
313   {
314     case GL_RGBA32F:
315     {
316       aFormat.SetNbComponents (4);
317       aFormat.SetInternalFormat (theSizedFormat);
318       aFormat.SetPixelFormat (GL_RGBA);
319       aFormat.SetDataType (GL_FLOAT);
320       return aFormat;
321     }
322     case GL_R32F:
323     {
324       aFormat.SetNbComponents (1);
325       aFormat.SetInternalFormat (theSizedFormat);
326       aFormat.SetPixelFormat (GL_RED);
327       aFormat.SetDataType (GL_FLOAT);
328       return aFormat;
329     }
330     case GL_RGBA16F:
331     {
332       aFormat.SetNbComponents (4);
333       aFormat.SetInternalFormat (theSizedFormat);
334       aFormat.SetPixelFormat (GL_RGBA);
335       aFormat.SetDataType (GL_HALF_FLOAT);
336       if (theCtx->hasHalfFloatBuffer == OpenGl_FeatureInExtensions)
337       {
338       #if defined(GL_ES_VERSION_2_0)
339         aFormat.SetDataType (GL_HALF_FLOAT_OES);
340       #else
341         aFormat.SetDataType (GL_FLOAT);
342       #endif
343       }
344       return aFormat;
345     }
346     case GL_R16F:
347     {
348       aFormat.SetNbComponents (1);
349       aFormat.SetInternalFormat (theSizedFormat);
350       aFormat.SetPixelFormat (GL_RED);
351       aFormat.SetDataType (GL_HALF_FLOAT);
352       if (theCtx->hasHalfFloatBuffer == OpenGl_FeatureInExtensions)
353       {
354       #if defined(GL_ES_VERSION_2_0)
355         aFormat.SetDataType (GL_HALF_FLOAT_OES);
356       #else
357         aFormat.SetDataType (GL_FLOAT);
358       #endif
359       }
360       return aFormat;
361     }
362     case GL_SRGB8_ALPHA8:
363     case GL_RGBA8:
364     case GL_RGBA:
365     {
366       aFormat.SetNbComponents (4);
367       aFormat.SetInternalFormat (theSizedFormat);
368       aFormat.SetPixelFormat (GL_RGBA);
369       aFormat.SetDataType (GL_UNSIGNED_BYTE);
370       if (theSizedFormat == GL_SRGB8_ALPHA8
371       && !theCtx->ToRenderSRGB())
372       {
373         aFormat.SetInternalFormat (GL_RGBA8); // fallback format
374       }
375       return aFormat;
376     }
377     case GL_SRGB8:
378     case GL_RGB8:
379     case GL_RGB:
380     {
381       aFormat.SetNbComponents (3);
382       aFormat.SetInternalFormat (theSizedFormat);
383       aFormat.SetPixelFormat (GL_RGB);
384       aFormat.SetDataType (GL_UNSIGNED_BYTE);
385       if (theSizedFormat == GL_SRGB8
386       && !theCtx->ToRenderSRGB())
387       {
388         aFormat.SetInternalFormat (GL_RGB8); // fallback format
389       }
390       return aFormat;
391     }
392     // integer types
393     case GL_R32I:
394     {
395       aFormat.SetNbComponents (1);
396       aFormat.SetInternalFormat (theSizedFormat);
397       aFormat.SetPixelFormat (GL_RED_INTEGER);
398       aFormat.SetDataType (GL_INT);
399       return aFormat;
400     }
401     case GL_RG32I:
402     {
403       aFormat.SetNbComponents (2);
404       aFormat.SetInternalFormat (theSizedFormat);
405       aFormat.SetPixelFormat (GL_RG_INTEGER);
406       aFormat.SetDataType (GL_INT);
407       return aFormat;
408     }
409     // depth formats
410     case GL_DEPTH24_STENCIL8:
411     {
412       aFormat.SetNbComponents (2);
413       aFormat.SetInternalFormat (theSizedFormat);
414       aFormat.SetPixelFormat (GL_DEPTH_STENCIL);
415       aFormat.SetDataType (GL_UNSIGNED_INT_24_8);
416       return aFormat;
417     }
418     case GL_DEPTH32F_STENCIL8:
419     {
420       aFormat.SetNbComponents (2);
421       aFormat.SetInternalFormat (theSizedFormat);
422       aFormat.SetPixelFormat (GL_DEPTH_STENCIL);
423       aFormat.SetDataType (GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
424       return aFormat;
425     }
426     case GL_DEPTH_COMPONENT16:
427     {
428       aFormat.SetNbComponents (1);
429       aFormat.SetInternalFormat (theSizedFormat);
430       aFormat.SetPixelFormat (GL_DEPTH_COMPONENT);
431       aFormat.SetDataType (GL_UNSIGNED_SHORT);
432       return aFormat;
433     }
434     case GL_DEPTH_COMPONENT24:
435     {
436       aFormat.SetNbComponents (1);
437       aFormat.SetInternalFormat (theSizedFormat);
438       aFormat.SetPixelFormat (GL_DEPTH_COMPONENT);
439       aFormat.SetDataType (GL_UNSIGNED_INT);
440       return aFormat;
441     }
442     case GL_DEPTH_COMPONENT32F:
443     {
444       aFormat.SetNbComponents (1);
445       aFormat.SetInternalFormat (theSizedFormat);
446       aFormat.SetPixelFormat (GL_DEPTH_COMPONENT);
447       aFormat.SetDataType (GL_FLOAT);
448       return aFormat;
449     }
450   }
451   return aFormat;
452 }
453
454 // =======================================================================
455 // function : FindCompressedFormat
456 // purpose  :
457 // =======================================================================
458 OpenGl_TextureFormat OpenGl_TextureFormat::FindCompressedFormat (const Handle(OpenGl_Context)& theCtx,
459                                                                  Image_CompressedFormat theFormat,
460                                                                  bool theIsColorMap)
461 {
462   OpenGl_TextureFormat aFormat;
463   if (!theCtx->SupportedTextureFormats()->IsSupported (theFormat))
464   {
465     return aFormat;
466   }
467
468   switch (theFormat)
469   {
470     case Image_CompressedFormat_UNKNOWN:
471     {
472       return aFormat;
473     }
474     case Image_CompressedFormat_RGB_S3TC_DXT1:
475     {
476       aFormat.SetNbComponents (3);
477       aFormat.SetPixelFormat (GL_RGB);
478       aFormat.SetDataType (GL_UNSIGNED_BYTE);
479       aFormat.SetInternalFormat (GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
480       if (theIsColorMap
481        && theCtx->ToRenderSRGB())
482       {
483         aFormat.SetInternalFormat (GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
484       }
485       return aFormat;
486     }
487     case Image_CompressedFormat_RGBA_S3TC_DXT1:
488     {
489       aFormat.SetNbComponents (4);
490       aFormat.SetPixelFormat (GL_RGBA);
491       aFormat.SetDataType (GL_UNSIGNED_BYTE);
492       aFormat.SetInternalFormat (GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
493       if (theIsColorMap
494        && theCtx->ToRenderSRGB())
495       {
496         aFormat.SetInternalFormat (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
497       }
498       return aFormat;
499     }
500     case Image_CompressedFormat_RGBA_S3TC_DXT3:
501     {
502       aFormat.SetNbComponents (4);
503       aFormat.SetPixelFormat (GL_RGBA);
504       aFormat.SetDataType (GL_UNSIGNED_BYTE);
505       aFormat.SetInternalFormat (GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
506       if (theIsColorMap
507        && theCtx->ToRenderSRGB())
508       {
509         aFormat.SetInternalFormat (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
510       }
511       return aFormat;
512     }
513     case Image_CompressedFormat_RGBA_S3TC_DXT5:
514     {
515       aFormat.SetNbComponents (4);
516       aFormat.SetPixelFormat (GL_RGBA);
517       aFormat.SetDataType (GL_UNSIGNED_BYTE);
518       aFormat.SetInternalFormat (GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
519       if (theIsColorMap
520        && theCtx->ToRenderSRGB())
521       {
522         aFormat.SetInternalFormat (GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
523       }
524       return aFormat;
525     }
526   }
527   return aFormat;
528 }