glcolorconvert: add support for the NV16 and NV61 formats
[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     case GST_VIDEO_FORMAT_NV16:
194     case GST_VIDEO_FORMAT_NV61:
195       n_plane_components = plane == 0 ? 1 : 2;
196       break;
197     case GST_VIDEO_FORMAT_GRAY8:
198     case GST_VIDEO_FORMAT_Y444:
199     case GST_VIDEO_FORMAT_Y42B:
200     case GST_VIDEO_FORMAT_Y41B:
201     case GST_VIDEO_FORMAT_I420:
202     case GST_VIDEO_FORMAT_YV12:
203       n_plane_components = 1;
204       break;
205     case GST_VIDEO_FORMAT_BGR10A2_LE:
206     case GST_VIDEO_FORMAT_RGB10A2_LE:
207     case GST_VIDEO_FORMAT_Y410:
208       return GST_GL_RGB10_A2;
209     case GST_VIDEO_FORMAT_P010_10LE:
210     case GST_VIDEO_FORMAT_P010_10BE:
211     case GST_VIDEO_FORMAT_P016_LE:
212     case GST_VIDEO_FORMAT_P016_BE:
213       return plane == 0 ? GST_GL_R16 : GST_GL_RG16;
214     default:
215       n_plane_components = 4;
216       g_assert_not_reached ();
217       break;
218   }
219
220   switch (n_plane_components) {
221     case 4:
222       return GST_GL_RGBA;
223     case 3:
224       return GST_GL_RGB;
225     case 2:
226       return texture_rg ? GST_GL_RG : GST_GL_LUMINANCE_ALPHA;
227     case 1:
228       return texture_rg ? GST_GL_RED : GST_GL_LUMINANCE;
229     default:
230       break;
231   }
232
233   g_critical ("Unknown video format 0x%x provided", v_format);
234   return 0;
235 }
236
237 /**
238  * gst_gl_sized_gl_format_from_gl_format_type:
239  * @context: a #GstGLContext
240  * @format: an OpenGL format, `GL_RGBA`, `GL_LUMINANCE`, etc
241  * @type: an OpenGL type, `GL_UNSIGNED_BYTE`, `GL_FLOAT`, etc
242  *
243  * Returns: the sized internal format specified by @format and @type that can
244  *          be used in @context
245  */
246 guint
247 gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
248     guint format, guint type)
249 {
250   gboolean ext_texture_rg =
251       gst_gl_context_check_feature (context, "GL_EXT_texture_rg");
252
253   switch (format) {
254     case GST_GL_RGBA:
255       switch (type) {
256         case GL_UNSIGNED_BYTE:
257           return USING_GLES2 (context)
258               && !USING_GLES3 (context) ? GST_GL_RGBA : GST_GL_RGBA8;
259         case GL_UNSIGNED_SHORT:
260           return GST_GL_RGBA16;
261         case GL_UNSIGNED_INT_2_10_10_10_REV:
262           return GST_GL_RGB10_A2;
263       }
264       break;
265     case GST_GL_RGB:
266       switch (type) {
267         case GL_UNSIGNED_BYTE:
268           return USING_GLES2 (context)
269               && !USING_GLES3 (context) ? GST_GL_RGB : GST_GL_RGB8;
270         case GL_UNSIGNED_SHORT_5_6_5:
271           return GST_GL_RGB565;
272         case GL_UNSIGNED_SHORT:
273           return GST_GL_RGB16;
274       }
275       break;
276     case GST_GL_RG:
277       switch (type) {
278         case GL_UNSIGNED_BYTE:
279           if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
280             return GST_GL_RG;
281           return GST_GL_RG8;
282         case GL_UNSIGNED_SHORT:
283           return GST_GL_RG16;
284       }
285       break;
286     case GST_GL_RED:
287       switch (type) {
288         case GL_UNSIGNED_BYTE:
289           if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
290             return GST_GL_RED;
291           return GST_GL_R8;
292         case GL_UNSIGNED_SHORT:
293           return GST_GL_R16;
294       }
295       break;
296     case GST_GL_RGBA8:
297     case GST_GL_RGBA16:
298     case GST_GL_RGB8:
299     case GST_GL_RGB16:
300     case GST_GL_RGB565:
301     case GST_GL_RG8:
302     case GST_GL_R8:
303     case GST_GL_LUMINANCE:
304     case GST_GL_LUMINANCE_ALPHA:
305     case GST_GL_ALPHA:
306     case GST_GL_DEPTH_COMPONENT16:
307     case GST_GL_DEPTH24_STENCIL8:
308     case GST_GL_RGB10_A2:
309     case GST_GL_R16:
310     case GST_GL_RG16:
311       return format;
312     default:
313       g_critical ("Unknown GL format 0x%x type 0x%x provided", format, type);
314       return format;
315   }
316
317   g_assert_not_reached ();
318   return 0;
319 }
320
321 /**
322  * gst_gl_format_type_from_sized_gl_format:
323  * @format: the sized internal #GstGLFormat
324  * @unsized_format: (out): location for the resulting unsized #GstGLFormat
325  * @gl_type: (out): location for the resulting GL type
326  *
327  * Get the unsized format and type from @format for usage in glReadPixels,
328  * glTex{Sub}Image*, glTexImage* and similar functions.
329  *
330  * Since: 1.16
331  */
332 void
333 gst_gl_format_type_from_sized_gl_format (GstGLFormat format,
334     GstGLFormat * unsized_format, guint * gl_type)
335 {
336   g_return_if_fail (unsized_format != NULL);
337   g_return_if_fail (gl_type != NULL);
338
339   switch (format) {
340     case GST_GL_RGBA8:
341       *unsized_format = GST_GL_RGBA;
342       *gl_type = GL_UNSIGNED_BYTE;
343       break;
344     case GST_GL_RGB8:
345       *unsized_format = GST_GL_RGB;
346       *gl_type = GL_UNSIGNED_BYTE;
347       break;
348     case GST_GL_RGBA16:
349       *unsized_format = GST_GL_RGBA;
350       *gl_type = GL_UNSIGNED_SHORT;
351       break;
352     case GST_GL_RGB16:
353       *unsized_format = GST_GL_RGB;
354       *gl_type = GL_UNSIGNED_SHORT;
355       break;
356     case GST_GL_RGB565:
357       *unsized_format = GST_GL_RGB;
358       *gl_type = GL_UNSIGNED_SHORT_5_6_5;
359       break;
360     case GST_GL_RG8:
361       *unsized_format = GST_GL_RG;
362       *gl_type = GL_UNSIGNED_BYTE;
363       break;
364     case GST_GL_R8:
365       *unsized_format = GST_GL_RED;
366       *gl_type = GL_UNSIGNED_BYTE;
367       break;
368     case GST_GL_RGBA:
369     case GST_GL_RGB:
370     case GST_GL_RG:
371     case GST_GL_RED:
372     case GST_GL_LUMINANCE:
373     case GST_GL_LUMINANCE_ALPHA:
374     case GST_GL_ALPHA:
375       *unsized_format = format;
376       *gl_type = GL_UNSIGNED_BYTE;
377       break;
378     case GST_GL_RGB10_A2:
379       *unsized_format = GST_GL_RGBA;
380       *gl_type = GL_UNSIGNED_INT_2_10_10_10_REV;
381       break;
382     case GST_GL_R16:
383       *unsized_format = GST_GL_RED;
384       *gl_type = GL_UNSIGNED_SHORT;
385       break;
386     case GST_GL_RG16:
387       *unsized_format = GST_GL_RG;
388       *gl_type = GL_UNSIGNED_SHORT;
389       break;
390     default:
391       g_critical ("Unknown GL format 0x%x provided", format);
392       *unsized_format = format;
393       *gl_type = GL_UNSIGNED_BYTE;
394       return;
395   }
396 }
397
398 /**
399  * gst_gl_format_is_supported:
400  * @context: a #GstGLContext
401  * @format: the #GstGLFormat to check is supported by @context
402  *
403  * Returns: Whether @format is supported by @context based on the OpenGL API,
404  *          version, or available OpenGL extension/s.
405  *
406  * Since: 1.16
407  */
408 gboolean
409 gst_gl_format_is_supported (GstGLContext * context, GstGLFormat format)
410 {
411   g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
412
413   switch (format) {
414     case GST_GL_RGBA:
415     case GST_GL_RGB:
416       return TRUE;
417     case GST_GL_LUMINANCE:
418     case GST_GL_ALPHA:
419     case GST_GL_LUMINANCE_ALPHA:
420       /* deprecated/removed in core GL3 contexts */
421       return USING_OPENGL (context) || USING_GLES2 (context);
422     case GST_GL_RG:
423     case GST_GL_RED:
424       return gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)
425           || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0)
426           || gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
427           || gst_gl_context_check_feature (context, "GL_ARB_texture_rg");
428     case GST_GL_R8:
429     case GST_GL_RG8:
430       return USING_GLES3 (context)
431           || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0)
432           || gst_gl_context_check_feature (context, "GL_ARB_texture_rg");
433     case GST_GL_RGB8:
434     case GST_GL_RGBA8:
435       return (USING_GLES3 (context) && !USING_GLES2 (context))
436           || USING_OPENGL (context) || USING_OPENGL3 (context);
437     case GST_GL_RGB16:
438     case GST_GL_RGBA16:
439       return USING_OPENGL (context) || USING_OPENGL3 (context)
440           || USING_GLES3 (context);
441     case GST_GL_RGB565:
442       return USING_GLES2 (context) || (USING_OPENGL3 (context)
443           && gst_gl_context_check_feature (context,
444               "GL_ARB_ES2_compatibility"));
445     case GST_GL_DEPTH_COMPONENT16:
446       return gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 4)
447           || USING_GLES2 (context)
448           || gst_gl_context_check_feature (context, "GL_ARB_depth_texture")
449           || gst_gl_context_check_feature (context, "GL_OES_depth_texture");
450     case GST_GL_DEPTH24_STENCIL8:
451       return gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 3, 0)
452           || USING_GLES3 (context)
453           || gst_gl_context_check_feature (context,
454           "GL_OES_packed_depth_stencil")
455           || gst_gl_context_check_feature (context,
456           "GL_EXT_packed_depth_stencil");
457     case GST_GL_RGB10_A2:
458       return USING_OPENGL (context) || USING_OPENGL3 (context)
459           || USING_GLES3 (context)
460           || gst_gl_context_check_feature (context,
461           "GL_OES_required_internalformat");
462     case GST_GL_R16:
463     case GST_GL_RG16:
464       return gst_gl_context_check_gl_version (context,
465           GST_GL_API_OPENGL | GST_GL_API_OPENGL3, 3, 0)
466           || (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 1)
467           && gst_gl_context_check_feature (context, "GL_EXT_texture_norm16"));
468     default:
469       g_assert_not_reached ();
470       return FALSE;
471   }
472 }
473
474 /**
475  * gst_gl_texture_target_to_string:
476  * @target: a #GstGLTextureTarget
477  *
478  * Returns: the stringified version of @target or %NULL
479  */
480 const gchar *
481 gst_gl_texture_target_to_string (GstGLTextureTarget target)
482 {
483   switch (target) {
484     case GST_GL_TEXTURE_TARGET_2D:
485       return GST_GL_TEXTURE_TARGET_2D_STR;
486     case GST_GL_TEXTURE_TARGET_RECTANGLE:
487       return GST_GL_TEXTURE_TARGET_RECTANGLE_STR;
488     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
489       return GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR;
490     default:
491       return NULL;
492   }
493 }
494
495 /**
496  * gst_gl_texture_target_from_string:
497  * @str: a string equivalent to one of the GST_GL_TEXTURE_TARGET_*_STR values
498  *
499  * Returns: the #GstGLTextureTarget represented by @str or
500  *          %GST_GL_TEXTURE_TARGET_NONE
501  */
502 GstGLTextureTarget
503 gst_gl_texture_target_from_string (const gchar * str)
504 {
505   if (!str)
506     return GST_GL_TEXTURE_TARGET_NONE;
507
508   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_2D_STR) == 0)
509     return GST_GL_TEXTURE_TARGET_2D;
510   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_RECTANGLE_STR) == 0)
511     return GST_GL_TEXTURE_TARGET_RECTANGLE;
512   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR) == 0)
513     return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
514
515   return GST_GL_TEXTURE_TARGET_NONE;
516 }
517
518 /**
519  * gst_gl_texture_target_to_gl:
520  * @target: a #GstGLTextureTarget
521  *
522  * Returns: the OpenGL value for binding the @target with glBindTexture() and
523  *          similar functions or 0
524  */
525 guint
526 gst_gl_texture_target_to_gl (GstGLTextureTarget target)
527 {
528   switch (target) {
529     case GST_GL_TEXTURE_TARGET_2D:
530       return GL_TEXTURE_2D;
531     case GST_GL_TEXTURE_TARGET_RECTANGLE:
532       return GL_TEXTURE_RECTANGLE;
533     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
534       return GL_TEXTURE_EXTERNAL_OES;
535     default:
536       return 0;
537   }
538 }
539
540 /**
541  * gst_gl_texture_target_from_gl:
542  * @target: an OpenGL texture binding target
543  *
544  * Returns: the #GstGLTextureTarget that's equiavalant to @target or
545  *          %GST_GL_TEXTURE_TARGET_NONE
546  */
547 GstGLTextureTarget
548 gst_gl_texture_target_from_gl (guint target)
549 {
550   switch (target) {
551     case GL_TEXTURE_2D:
552       return GST_GL_TEXTURE_TARGET_2D;
553     case GL_TEXTURE_RECTANGLE:
554       return GST_GL_TEXTURE_TARGET_RECTANGLE;
555     case GL_TEXTURE_EXTERNAL_OES:
556       return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
557     default:
558       return GST_GL_TEXTURE_TARGET_NONE;
559   }
560 }
561
562 /**
563  * gst_gl_texture_target_to_buffer_pool_option:
564  * @target: a #GstGLTextureTarget
565  *
566  * Returns: a string representing the @GstBufferPoolOption specified by @target
567  */
568 const gchar *
569 gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target)
570 {
571   switch (target) {
572     case GST_GL_TEXTURE_TARGET_2D:
573       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D;
574     case GST_GL_TEXTURE_TARGET_RECTANGLE:
575       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE;
576     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
577       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES;
578     default:
579       return NULL;
580   }
581 }