66967086e1cc6a93ca1178746fc9a3a69671fa42
[platform/upstream/gst-plugins-base.git] / gst-libs / gst / gl / gstglformat.c
1 /*
2  * GStreamer
3  * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * SECTION:gstglformat
23  * @title: GstGLFormat
24  * @short_description: utilities for dealing with OpenGL formats
25  * @see_also: #GstGLBaseMemory, #GstGLMemory, #GstGLFramebuffer, #GstGLBuffer
26  *
27  * Some useful utilities for converting between various formats and OpenGL
28  * formats.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "gstglformat.h"
36
37 #include "gstglcontext.h"
38 #include "gstglfuncs.h"
39
40 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
41 #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
42 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
43 #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
44 #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
45
46 #ifndef GL_TEXTURE_RECTANGLE
47 #define GL_TEXTURE_RECTANGLE 0x84F5
48 #endif
49 #ifndef GL_TEXTURE_EXTERNAL_OES
50 #define GL_TEXTURE_EXTERNAL_OES 0x8D65
51 #endif
52 #ifndef GL_UNSIGNED_INT_2_10_10_10_REV
53 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
54 #endif
55
56 static inline guint
57 _gl_format_n_components (guint format)
58 {
59   switch (format) {
60     case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
61     case GST_GL_RGBA:
62     case GST_GL_RGBA8:
63     case GST_GL_RGBA16:
64     case GST_GL_RGB10_A2:
65       return 4;
66     case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
67     case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
68     case GST_GL_RGB:
69     case GST_GL_RGB8:
70     case GST_GL_RGB16:
71     case GST_GL_RGB565:
72       return 3;
73     case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
74     case GST_VIDEO_GL_TEXTURE_TYPE_RG:
75     case GST_GL_LUMINANCE_ALPHA:
76     case GST_GL_RG:
77     case GST_GL_RG8:
78     case GST_GL_RG16:
79       return 2;
80     case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
81     case GST_VIDEO_GL_TEXTURE_TYPE_R:
82     case GST_GL_LUMINANCE:
83     case GST_GL_ALPHA:
84     case GST_GL_RED:
85     case GST_GL_R8:
86     case GST_GL_R16:
87       return 1;
88     default:
89       return 0;
90   }
91 }
92
93 static inline guint
94 _gl_type_n_components (guint type)
95 {
96   switch (type) {
97     case GL_UNSIGNED_BYTE:
98     case GL_UNSIGNED_SHORT:
99       return 1;
100     case GL_UNSIGNED_SHORT_5_6_5:
101       return 3;
102     case GL_UNSIGNED_INT_2_10_10_10_REV:
103       return 4;
104     default:
105       g_assert_not_reached ();
106       return 0;
107   }
108 }
109
110 static inline guint
111 _gl_type_n_bytes (guint type)
112 {
113   switch (type) {
114     case GL_UNSIGNED_BYTE:
115       return 1;
116     case GL_UNSIGNED_SHORT:
117     case GL_UNSIGNED_SHORT_5_6_5:
118       return 2;
119     case GL_UNSIGNED_INT_2_10_10_10_REV:
120       return 4;
121     default:
122       g_assert_not_reached ();
123       return 0;
124   }
125 }
126
127 /**
128  * gst_gl_format_type_n_bytes:
129  * @format: the OpenGL format, `GL_RGBA`, `GL_LUMINANCE`, etc
130  * @type: the OpenGL type, `GL_UNSIGNED_BYTE`, `GL_FLOAT`, etc
131  *
132  * Returns: the number of bytes the specified @format, @type combination takes
133  * per pixel
134  */
135 guint
136 gst_gl_format_type_n_bytes (guint format, guint type)
137 {
138   return _gl_format_n_components (format) / _gl_type_n_components (type) *
139       _gl_type_n_bytes (type);
140 }
141
142 /**
143  * gst_gl_format_from_video_info:
144  * @context: a #GstGLContext
145  * @vinfo: a #GstVideoInfo
146  * @plane: the plane number in @vinfo
147  *
148  * Returns: the #GstGLFormat necessary for holding the data in @plane of @vinfo
149  */
150 GstGLFormat
151 gst_gl_format_from_video_info (GstGLContext * context, GstVideoInfo * vinfo,
152     guint plane)
153 {
154   gboolean texture_rg =
155       gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
156       || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)
157       || gst_gl_context_check_feature (context, "GL_ARB_texture_rg")
158       || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0);
159   GstVideoFormat v_format = GST_VIDEO_INFO_FORMAT (vinfo);
160   guint n_plane_components;
161
162   switch (v_format) {
163     case GST_VIDEO_FORMAT_RGBx:
164     case GST_VIDEO_FORMAT_BGRx:
165     case GST_VIDEO_FORMAT_xRGB:
166     case GST_VIDEO_FORMAT_xBGR:
167     case GST_VIDEO_FORMAT_RGBA:
168     case GST_VIDEO_FORMAT_BGRA:
169     case GST_VIDEO_FORMAT_ARGB:
170     case GST_VIDEO_FORMAT_ABGR:
171     case GST_VIDEO_FORMAT_AYUV:
172     case GST_VIDEO_FORMAT_VUYA:
173       n_plane_components = 4;
174       break;
175     case GST_VIDEO_FORMAT_ARGB64:
176       return GST_GL_RGBA16;
177     case GST_VIDEO_FORMAT_RGB:
178     case GST_VIDEO_FORMAT_BGR:
179       n_plane_components = 3;
180       break;
181     case GST_VIDEO_FORMAT_RGB16:
182     case GST_VIDEO_FORMAT_BGR16:
183       return GST_GL_RGB565;
184       break;
185     case GST_VIDEO_FORMAT_GRAY16_BE:
186     case GST_VIDEO_FORMAT_GRAY16_LE:
187     case GST_VIDEO_FORMAT_YUY2:
188     case GST_VIDEO_FORMAT_UYVY:
189       n_plane_components = 2;
190       break;
191     case GST_VIDEO_FORMAT_NV12:
192     case GST_VIDEO_FORMAT_NV21:
193       n_plane_components = plane == 0 ? 1 : 2;
194       break;
195     case GST_VIDEO_FORMAT_GRAY8:
196     case GST_VIDEO_FORMAT_Y444:
197     case GST_VIDEO_FORMAT_Y42B:
198     case GST_VIDEO_FORMAT_Y41B:
199     case GST_VIDEO_FORMAT_I420:
200     case GST_VIDEO_FORMAT_YV12:
201       n_plane_components = 1;
202       break;
203     case GST_VIDEO_FORMAT_BGR10A2_LE:
204     case GST_VIDEO_FORMAT_RGB10A2_LE:
205     case GST_VIDEO_FORMAT_Y410:
206       return GST_GL_RGB10_A2;
207     case GST_VIDEO_FORMAT_P010_10LE:
208     case GST_VIDEO_FORMAT_P010_10BE:
209     case GST_VIDEO_FORMAT_P016_LE:
210     case GST_VIDEO_FORMAT_P016_BE:
211       return plane == 0 ? GST_GL_R16 : GST_GL_RG16;
212     default:
213       n_plane_components = 4;
214       g_assert_not_reached ();
215       break;
216   }
217
218   switch (n_plane_components) {
219     case 4:
220       return GST_GL_RGBA;
221     case 3:
222       return GST_GL_RGB;
223     case 2:
224       return texture_rg ? GST_GL_RG : GST_GL_LUMINANCE_ALPHA;
225     case 1:
226       return texture_rg ? GST_GL_RED : GST_GL_LUMINANCE;
227     default:
228       break;
229   }
230
231   g_critical ("Unknown video format 0x%x provided", v_format);
232   return 0;
233 }
234
235 /**
236  * gst_gl_sized_gl_format_from_gl_format_type:
237  * @context: a #GstGLContext
238  * @format: an OpenGL format, `GL_RGBA`, `GL_LUMINANCE`, etc
239  * @type: an OpenGL type, `GL_UNSIGNED_BYTE`, `GL_FLOAT`, etc
240  *
241  * Returns: the sized internal format specified by @format and @type that can
242  *          be used in @context
243  */
244 guint
245 gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
246     guint format, guint type)
247 {
248   gboolean ext_texture_rg =
249       gst_gl_context_check_feature (context, "GL_EXT_texture_rg");
250
251   switch (format) {
252     case GST_GL_RGBA:
253       switch (type) {
254         case GL_UNSIGNED_BYTE:
255           return USING_GLES2 (context)
256               && !USING_GLES3 (context) ? GST_GL_RGBA : GST_GL_RGBA8;
257         case GL_UNSIGNED_SHORT:
258           return GST_GL_RGBA16;
259         case GL_UNSIGNED_INT_2_10_10_10_REV:
260           return GST_GL_RGB10_A2;
261       }
262       break;
263     case GST_GL_RGB:
264       switch (type) {
265         case GL_UNSIGNED_BYTE:
266           return USING_GLES2 (context)
267               && !USING_GLES3 (context) ? GST_GL_RGB : GST_GL_RGB8;
268         case GL_UNSIGNED_SHORT_5_6_5:
269           return GST_GL_RGB565;
270         case GL_UNSIGNED_SHORT:
271           return GST_GL_RGB16;
272       }
273       break;
274     case GST_GL_RG:
275       switch (type) {
276         case GL_UNSIGNED_BYTE:
277           if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
278             return GST_GL_RG;
279           return GST_GL_RG8;
280         case GL_UNSIGNED_SHORT:
281           return GST_GL_RG16;
282       }
283       break;
284     case GST_GL_RED:
285       switch (type) {
286         case GL_UNSIGNED_BYTE:
287           if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
288             return GST_GL_RED;
289           return GST_GL_R8;
290         case GL_UNSIGNED_SHORT:
291           return GST_GL_R16;
292       }
293       break;
294     case GST_GL_RGBA8:
295     case GST_GL_RGBA16:
296     case GST_GL_RGB8:
297     case GST_GL_RGB16:
298     case GST_GL_RGB565:
299     case GST_GL_RG8:
300     case GST_GL_R8:
301     case GST_GL_LUMINANCE:
302     case GST_GL_LUMINANCE_ALPHA:
303     case GST_GL_ALPHA:
304     case GST_GL_DEPTH_COMPONENT16:
305     case GST_GL_DEPTH24_STENCIL8:
306     case GST_GL_RGB10_A2:
307     case GST_GL_R16:
308     case GST_GL_RG16:
309       return format;
310     default:
311       g_critical ("Unknown GL format 0x%x type 0x%x provided", format, type);
312       return format;
313   }
314
315   g_assert_not_reached ();
316   return 0;
317 }
318
319 /**
320  * gst_gl_format_type_from_sized_gl_format:
321  * @format: the sized internal #GstGLFormat
322  * @unsized_format: (out): location for the resulting unsized #GstGLFormat
323  * @gl_type: (out): location for the resulting GL type
324  *
325  * Get the unsized format and type from @format for usage in glReadPixels,
326  * glTex{Sub}Image*, glTexImage* and similar functions.
327  *
328  * Since: 1.16
329  */
330 void
331 gst_gl_format_type_from_sized_gl_format (GstGLFormat format,
332     GstGLFormat * unsized_format, guint * gl_type)
333 {
334   g_return_if_fail (unsized_format != NULL);
335   g_return_if_fail (gl_type != NULL);
336
337   switch (format) {
338     case GST_GL_RGBA8:
339       *unsized_format = GST_GL_RGBA;
340       *gl_type = GL_UNSIGNED_BYTE;
341       break;
342     case GST_GL_RGB8:
343       *unsized_format = GST_GL_RGB;
344       *gl_type = GL_UNSIGNED_BYTE;
345       break;
346     case GST_GL_RGBA16:
347       *unsized_format = GST_GL_RGBA;
348       *gl_type = GL_UNSIGNED_SHORT;
349       break;
350     case GST_GL_RGB16:
351       *unsized_format = GST_GL_RGB;
352       *gl_type = GL_UNSIGNED_SHORT;
353       break;
354     case GST_GL_RGB565:
355       *unsized_format = GST_GL_RGB;
356       *gl_type = GL_UNSIGNED_SHORT_5_6_5;
357       break;
358     case GST_GL_RG8:
359       *unsized_format = GST_GL_RG;
360       *gl_type = GL_UNSIGNED_BYTE;
361       break;
362     case GST_GL_R8:
363       *unsized_format = GST_GL_RED;
364       *gl_type = GL_UNSIGNED_BYTE;
365       break;
366     case GST_GL_RGBA:
367     case GST_GL_RGB:
368     case GST_GL_RG:
369     case GST_GL_RED:
370     case GST_GL_LUMINANCE:
371     case GST_GL_LUMINANCE_ALPHA:
372     case GST_GL_ALPHA:
373       *unsized_format = format;
374       *gl_type = GL_UNSIGNED_BYTE;
375       break;
376     case GST_GL_RGB10_A2:
377       *unsized_format = GST_GL_RGBA;
378       *gl_type = GL_UNSIGNED_INT_2_10_10_10_REV;
379       break;
380     case GST_GL_R16:
381       *unsized_format = GST_GL_RED;
382       *gl_type = GL_UNSIGNED_SHORT;
383       break;
384     case GST_GL_RG16:
385       *unsized_format = GST_GL_RG;
386       *gl_type = GL_UNSIGNED_SHORT;
387       break;
388     default:
389       g_critical ("Unknown GL format 0x%x provided", format);
390       *unsized_format = format;
391       *gl_type = GL_UNSIGNED_BYTE;
392       return;
393   }
394 }
395
396 /**
397  * gst_gl_format_is_supported:
398  * @context: a #GstGLContext
399  * @format: the #GstGLFormat to check is supported by @context
400  *
401  * Returns: Whether @format is supported by @context based on the OpenGL API,
402  *          version, or available OpenGL extension/s.
403  *
404  * Since: 1.16
405  */
406 gboolean
407 gst_gl_format_is_supported (GstGLContext * context, GstGLFormat format)
408 {
409   g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
410
411   switch (format) {
412     case GST_GL_RGBA:
413     case GST_GL_RGB:
414       return TRUE;
415     case GST_GL_LUMINANCE:
416     case GST_GL_ALPHA:
417     case GST_GL_LUMINANCE_ALPHA:
418       /* deprecated/removed in core GL3 contexts */
419       return USING_OPENGL (context) || USING_GLES2 (context);
420     case GST_GL_RG:
421     case GST_GL_RED:
422       return gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)
423           || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0)
424           || gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
425           || gst_gl_context_check_feature (context, "GL_ARB_texture_rg");
426     case GST_GL_R8:
427     case GST_GL_RG8:
428       return USING_GLES3 (context)
429           || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0)
430           || gst_gl_context_check_feature (context, "GL_ARB_texture_rg");
431     case GST_GL_RGB8:
432     case GST_GL_RGBA8:
433       return (USING_GLES3 (context) && !USING_GLES2 (context))
434           || USING_OPENGL (context) || USING_OPENGL3 (context);
435     case GST_GL_RGB16:
436     case GST_GL_RGBA16:
437       return USING_OPENGL (context) || USING_OPENGL3 (context)
438           || USING_GLES3 (context);
439     case GST_GL_RGB565:
440       return USING_GLES2 (context) || (USING_OPENGL3 (context)
441           && gst_gl_context_check_feature (context,
442               "GL_ARB_ES2_compatibility"));
443     case GST_GL_DEPTH_COMPONENT16:
444       return gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 4)
445           || USING_GLES2 (context)
446           || gst_gl_context_check_feature (context, "GL_ARB_depth_texture")
447           || gst_gl_context_check_feature (context, "GL_OES_depth_texture");
448     case GST_GL_DEPTH24_STENCIL8:
449       return gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 3, 0)
450           || USING_GLES3 (context)
451           || gst_gl_context_check_feature (context,
452           "GL_OES_packed_depth_stencil")
453           || gst_gl_context_check_feature (context,
454           "GL_EXT_packed_depth_stencil");
455     case GST_GL_RGB10_A2:
456       return USING_OPENGL (context) || USING_OPENGL3 (context)
457           || USING_GLES3 (context)
458           || gst_gl_context_check_feature (context,
459           "GL_OES_required_internalformat");
460     case GST_GL_R16:
461     case GST_GL_RG16:
462       return gst_gl_context_check_gl_version (context,
463           GST_GL_API_OPENGL | GST_GL_API_OPENGL3, 3, 0)
464           || (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 1)
465           && gst_gl_context_check_feature (context, "GL_EXT_texture_norm16"));
466     default:
467       g_assert_not_reached ();
468       return FALSE;
469   }
470 }
471
472 /**
473  * gst_gl_texture_target_to_string:
474  * @target: a #GstGLTextureTarget
475  *
476  * Returns: the stringified version of @target or %NULL
477  */
478 const gchar *
479 gst_gl_texture_target_to_string (GstGLTextureTarget target)
480 {
481   switch (target) {
482     case GST_GL_TEXTURE_TARGET_2D:
483       return GST_GL_TEXTURE_TARGET_2D_STR;
484     case GST_GL_TEXTURE_TARGET_RECTANGLE:
485       return GST_GL_TEXTURE_TARGET_RECTANGLE_STR;
486     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
487       return GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR;
488     default:
489       return NULL;
490   }
491 }
492
493 /**
494  * gst_gl_texture_target_from_string:
495  * @str: a string equivalent to one of the GST_GL_TEXTURE_TARGET_*_STR values
496  *
497  * Returns: the #GstGLTextureTarget represented by @str or
498  *          %GST_GL_TEXTURE_TARGET_NONE
499  */
500 GstGLTextureTarget
501 gst_gl_texture_target_from_string (const gchar * str)
502 {
503   if (!str)
504     return GST_GL_TEXTURE_TARGET_NONE;
505
506   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_2D_STR) == 0)
507     return GST_GL_TEXTURE_TARGET_2D;
508   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_RECTANGLE_STR) == 0)
509     return GST_GL_TEXTURE_TARGET_RECTANGLE;
510   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR) == 0)
511     return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
512
513   return GST_GL_TEXTURE_TARGET_NONE;
514 }
515
516 /**
517  * gst_gl_texture_target_to_gl:
518  * @target: a #GstGLTextureTarget
519  *
520  * Returns: the OpenGL value for binding the @target with glBindTexture() and
521  *          similar functions or 0
522  */
523 guint
524 gst_gl_texture_target_to_gl (GstGLTextureTarget target)
525 {
526   switch (target) {
527     case GST_GL_TEXTURE_TARGET_2D:
528       return GL_TEXTURE_2D;
529     case GST_GL_TEXTURE_TARGET_RECTANGLE:
530       return GL_TEXTURE_RECTANGLE;
531     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
532       return GL_TEXTURE_EXTERNAL_OES;
533     default:
534       return 0;
535   }
536 }
537
538 /**
539  * gst_gl_texture_target_from_gl:
540  * @target: an OpenGL texture binding target
541  *
542  * Returns: the #GstGLTextureTarget that's equiavalant to @target or
543  *          %GST_GL_TEXTURE_TARGET_NONE
544  */
545 GstGLTextureTarget
546 gst_gl_texture_target_from_gl (guint target)
547 {
548   switch (target) {
549     case GL_TEXTURE_2D:
550       return GST_GL_TEXTURE_TARGET_2D;
551     case GL_TEXTURE_RECTANGLE:
552       return GST_GL_TEXTURE_TARGET_RECTANGLE;
553     case GL_TEXTURE_EXTERNAL_OES:
554       return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
555     default:
556       return GST_GL_TEXTURE_TARGET_NONE;
557   }
558 }
559
560 /**
561  * gst_gl_texture_target_to_buffer_pool_option:
562  * @target: a #GstGLTextureTarget
563  *
564  * Returns: a string representing the @GstBufferPoolOption specified by @target
565  */
566 const gchar *
567 gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target)
568 {
569   switch (target) {
570     case GST_GL_TEXTURE_TARGET_2D:
571       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D;
572     case GST_GL_TEXTURE_TARGET_RECTANGLE:
573       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE;
574     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
575       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES;
576     default:
577       return NULL;
578   }
579 }