gl/format: correct return enums in gst_gl_format_from_video_info
[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  * @short_description: utilities for dealing with OpenGL formats
24  * @see_also: #GstGLBaseMemory, #GstGLMemory, #GstGLFramebuffer, #GstGLBuffer
25  *
26  * Some useful utilities for converting between various formats and OpenGL
27  * formats.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <gst/gl/gstglformat.h>
35 #include <gst/gl/gstglcontext.h>
36
37 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
38 #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
39 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
40 #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
41 #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
42
43 #ifndef GL_TEXTURE_RECTANGLE
44 #define GL_TEXTURE_RECTANGLE 0x84F5
45 #endif
46 #ifndef GL_TEXTURE_EXTERNAL_OES
47 #define GL_TEXTURE_EXTERNAL_OES 0x8D65
48 #endif
49
50 static inline guint
51 _gl_format_n_components (guint format)
52 {
53   switch (format) {
54     case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
55     case GST_GL_RGBA:
56       return 4;
57     case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
58     case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
59     case GST_GL_RGB:
60       return 3;
61     case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
62     case GST_VIDEO_GL_TEXTURE_TYPE_RG:
63     case GST_GL_LUMINANCE_ALPHA:
64     case GST_GL_RG:
65       return 2;
66     case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
67     case GST_VIDEO_GL_TEXTURE_TYPE_R:
68     case GST_GL_LUMINANCE:
69     case GST_GL_RED:
70       return 1;
71     default:
72       return 0;
73   }
74 }
75
76 static inline guint
77 _gl_type_n_components (guint type)
78 {
79   switch (type) {
80     case GL_UNSIGNED_BYTE:
81       return 1;
82     case GL_UNSIGNED_SHORT_5_6_5:
83       return 3;
84     default:
85       g_assert_not_reached ();
86       return 0;
87   }
88 }
89
90 static inline guint
91 _gl_type_n_bytes (guint type)
92 {
93   switch (type) {
94     case GL_UNSIGNED_BYTE:
95       return 1;
96     case GL_UNSIGNED_SHORT_5_6_5:
97       return 2;
98     default:
99       g_assert_not_reached ();
100       return 0;
101   }
102 }
103
104 /**
105  * gst_gl_format_type_n_bytes:
106  * @format: the OpenGL format, %GL_RGBA, %GL_LUMINANCE, etc
107  * @type: the OpenGL type, %GL_UNSIGNED_BYTE, %GL_FLOAT, etc
108  *
109  * Returns: the number of bytes the specified @format, @type combination takes
110  * per pixel
111  */
112 guint
113 gst_gl_format_type_n_bytes (guint format, guint type)
114 {
115   return _gl_format_n_components (format) / _gl_type_n_components (type) *
116       _gl_type_n_bytes (type);
117 }
118
119 /**
120  * gst_gl_format_from_video_info:
121  * @context: a #GstGLContext
122  * @vinfo: a #GstVideoInfo
123  * @plane: the plane number in @vinfo
124  *
125  * Returns: the #GstGLFormat necessary for holding the data in @plane of @vinfo
126  */
127 GstGLFormat
128 gst_gl_format_from_video_info (GstGLContext * context, GstVideoInfo * vinfo,
129     guint plane)
130 {
131   gboolean texture_rg =
132       gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
133       || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)
134       || gst_gl_context_check_feature (context, "GL_ARB_texture_rg")
135       || gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 0);
136   GstVideoFormat v_format = GST_VIDEO_INFO_FORMAT (vinfo);
137   guint n_plane_components;
138
139   switch (v_format) {
140     case GST_VIDEO_FORMAT_RGBx:
141     case GST_VIDEO_FORMAT_BGRx:
142     case GST_VIDEO_FORMAT_xRGB:
143     case GST_VIDEO_FORMAT_xBGR:
144     case GST_VIDEO_FORMAT_RGBA:
145     case GST_VIDEO_FORMAT_BGRA:
146     case GST_VIDEO_FORMAT_ARGB:
147     case GST_VIDEO_FORMAT_ABGR:
148     case GST_VIDEO_FORMAT_AYUV:
149       n_plane_components = 4;
150       break;
151     case GST_VIDEO_FORMAT_RGB:
152     case GST_VIDEO_FORMAT_BGR:
153       n_plane_components = 3;
154       break;
155     case GST_VIDEO_FORMAT_RGB16:
156     case GST_VIDEO_FORMAT_BGR16:
157       return GST_GL_RGB565;
158     case GST_VIDEO_FORMAT_GRAY16_BE:
159     case GST_VIDEO_FORMAT_GRAY16_LE:
160     case GST_VIDEO_FORMAT_YUY2:
161     case GST_VIDEO_FORMAT_UYVY:
162       n_plane_components = 2;
163       break;
164     case GST_VIDEO_FORMAT_NV12:
165     case GST_VIDEO_FORMAT_NV21:
166       n_plane_components = plane == 0 ? 1 : 2;
167       break;
168     case GST_VIDEO_FORMAT_GRAY8:
169     case GST_VIDEO_FORMAT_Y444:
170     case GST_VIDEO_FORMAT_Y42B:
171     case GST_VIDEO_FORMAT_Y41B:
172     case GST_VIDEO_FORMAT_I420:
173     case GST_VIDEO_FORMAT_YV12:
174       n_plane_components = 1;
175       break;
176     default:
177       n_plane_components = 4;
178       g_assert_not_reached ();
179       break;
180   }
181
182   switch (n_plane_components) {
183     case 4:
184       return GST_GL_RGBA;
185       break;
186     case 3:
187       return GST_GL_RGB;
188       break;
189     case 2:
190       return texture_rg ? GST_GL_RG : GST_GL_LUMINANCE_ALPHA;
191       break;
192     case 1:
193       return texture_rg ? GST_GL_RED : GST_GL_LUMINANCE;
194       break;
195     default:
196       g_assert_not_reached ();
197       break;
198   }
199
200   return GST_GL_RGBA;
201 }
202
203 /**
204  * gst_gl_sized_gl_format_from_gl_format_type:
205  * @context: a #GstGLContext
206  * @format: an OpenGL format, %GL_RGBA, %GL_LUMINANCE, etc
207  * @type: an OpenGL type, %GL_UNSIGNED_BYTE, %GL_FLOAT, etc
208  *
209  * Returns: the sized internal format specified by @format and @type that can
210  *          be used in @context
211  */
212 guint
213 gst_gl_sized_gl_format_from_gl_format_type (GstGLContext * context,
214     guint format, guint type)
215 {
216   gboolean ext_texture_rg =
217       gst_gl_context_check_feature (context, "GL_EXT_texture_rg");
218
219   switch (format) {
220     case GST_GL_RGBA:
221       switch (type) {
222         case GL_UNSIGNED_BYTE:
223           return USING_GLES2 (context)
224               && !USING_GLES3 (context) ? GST_GL_RGBA : GST_GL_RGBA8;
225           break;
226       }
227       break;
228     case GST_GL_RGB:
229       switch (type) {
230         case GL_UNSIGNED_BYTE:
231           return USING_GLES2 (context)
232               && !USING_GLES3 (context) ? GST_GL_RGB : GST_GL_RGB8;
233           break;
234         case GL_UNSIGNED_SHORT_5_6_5:
235           return GST_GL_RGB;
236           break;
237       }
238       break;
239     case GST_GL_RG:
240       switch (type) {
241         case GL_UNSIGNED_BYTE:
242           if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
243             return GST_GL_RG;
244           return GST_GL_RG8;
245           break;
246       }
247       break;
248     case GST_GL_RED:
249       switch (type) {
250         case GL_UNSIGNED_BYTE:
251           if (!USING_GLES3 (context) && USING_GLES2 (context) && ext_texture_rg)
252             return GST_GL_RED;
253           return GST_GL_R8;
254           break;
255       }
256       break;
257     case GST_GL_RGBA8:
258     case GST_GL_RGB8:
259     case GST_GL_RG8:
260     case GST_GL_R8:
261     case GST_GL_LUMINANCE:
262     case GST_GL_LUMINANCE_ALPHA:
263     case GST_GL_ALPHA:
264     case GST_GL_DEPTH_COMPONENT16:
265     case GST_GL_DEPTH24_STENCIL8:
266       return format;
267     default:
268       break;
269   }
270
271   g_assert_not_reached ();
272   return 0;
273 }
274
275 /**
276  * gst_gl_texture_target_to_string:
277  * @target: a #GstGLTextureTarget
278  *
279  * Returns: the stringified version of @target or %NULL
280  */
281 const gchar *
282 gst_gl_texture_target_to_string (GstGLTextureTarget target)
283 {
284   switch (target) {
285     case GST_GL_TEXTURE_TARGET_2D:
286       return GST_GL_TEXTURE_TARGET_2D_STR;
287     case GST_GL_TEXTURE_TARGET_RECTANGLE:
288       return GST_GL_TEXTURE_TARGET_RECTANGLE_STR;
289     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
290       return GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR;
291     default:
292       return NULL;
293   }
294 }
295
296 /**
297  * gst_gl_texture_target_from_string:
298  * @str: a string equivalant to one of the GST_GL_TEXTURE_TARGET_*_STR values
299  *
300  * Returns: the #GstGLTextureTarget represented by @str or
301  *          %GST_GL_TEXTURE_TARGET_NONE
302  */
303 GstGLTextureTarget
304 gst_gl_texture_target_from_string (const gchar * str)
305 {
306   if (!str)
307     return GST_GL_TEXTURE_TARGET_NONE;
308
309   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_2D_STR) == 0)
310     return GST_GL_TEXTURE_TARGET_2D;
311   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_RECTANGLE_STR) == 0)
312     return GST_GL_TEXTURE_TARGET_RECTANGLE;
313   if (g_strcmp0 (str, GST_GL_TEXTURE_TARGET_EXTERNAL_OES_STR) == 0)
314     return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
315
316   return GST_GL_TEXTURE_TARGET_NONE;
317 }
318
319 /**
320  * gst_gl_texture_target_to_gl:
321  * @target: a #GstGLTextureTarget
322  *
323  * Returns: the OpenGL value for binding the @target with glBindTexture() and
324  *          similar functions or 0
325  */
326 guint
327 gst_gl_texture_target_to_gl (GstGLTextureTarget target)
328 {
329   switch (target) {
330     case GST_GL_TEXTURE_TARGET_2D:
331       return GL_TEXTURE_2D;
332     case GST_GL_TEXTURE_TARGET_RECTANGLE:
333       return GL_TEXTURE_RECTANGLE;
334     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
335       return GL_TEXTURE_EXTERNAL_OES;
336     default:
337       return 0;
338   }
339 }
340
341 /**
342  * gst_gl_texture_target_from_gl:
343  * @target: an OpenGL texture binding target
344  *
345  * Returns: the #GstGLTextureTarget that's equiavalant to @target or
346  *          %GST_GL_TEXTURE_TARGET_NONE
347  */
348 GstGLTextureTarget
349 gst_gl_texture_target_from_gl (guint target)
350 {
351   switch (target) {
352     case GL_TEXTURE_2D:
353       return GST_GL_TEXTURE_TARGET_2D;
354     case GL_TEXTURE_RECTANGLE:
355       return GST_GL_TEXTURE_TARGET_RECTANGLE;
356     case GL_TEXTURE_EXTERNAL_OES:
357       return GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
358     default:
359       return GST_GL_TEXTURE_TARGET_NONE;
360   }
361 }
362
363 /**
364  * gst_gl_texture_target_to_buffer_pool_option:
365  * @target: a #GstGLTextureTarget
366  *
367  * Returns: a string representing the @GstBufferPoolOption specified by @target
368  */
369 const gchar *
370 gst_gl_texture_target_to_buffer_pool_option (GstGLTextureTarget target)
371 {
372   switch (target) {
373     case GST_GL_TEXTURE_TARGET_2D:
374       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D;
375     case GST_GL_TEXTURE_TARGET_RECTANGLE:
376       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE;
377     case GST_GL_TEXTURE_TARGET_EXTERNAL_OES:
378       return GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES;
379     default:
380       return NULL;
381   }
382 }