1 /*****************************************************************************
2  * converter.h: OpenGL internal header
3  *****************************************************************************
4  * Copyright (C) 2016 VLC authors and VideoLAN
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20 
21 #ifndef VLC_OPENGL_CONVERTER_H
22 #define VLC_OPENGL_CONVERTER_H
23 
24 #include <vlc_plugin.h>
25 #include <vlc_common.h>
26 #include <vlc_picture_pool.h>
27 #include <vlc_opengl.h>
28 
29 /* if USE_OPENGL_ES2 is defined, OpenGL ES version 2 will be used, otherwise
30  * normal OpenGL will be used */
31 #ifdef __APPLE__
32 # include <TargetConditionals.h>
33 # if !TARGET_OS_IPHONE
34 #  undef USE_OPENGL_ES2
35 #  define MACOS_OPENGL
36 #  include <OpenGL/gl.h>
37 # else /* Force ESv2 on iOS */
38 #  define USE_OPENGL_ES2
39 #  include <OpenGLES/ES1/gl.h>
40 #  include <OpenGLES/ES2/gl.h>
41 #  include <OpenGLES/ES2/glext.h>
42 # endif
43 #else /* !defined (__APPLE__) */
44 # if defined (USE_OPENGL_ES2)
45 #  include <GLES2/gl2.h>
46 #  include <GLES2/gl2ext.h>
47 # else
48 #  ifdef _WIN32
49 #   include <GL/glew.h>
50 #  endif
51 #  include <GL/gl.h>
52 # endif
53 #endif
54 
55 #define VLCGL_PICTURE_MAX 128
56 
57 #ifndef GL_TEXTURE_RECTANGLE
58 # define GL_TEXTURE_RECTANGLE 0x84F5
59 #endif
60 
61 #ifndef APIENTRY
62 # define APIENTRY
63 #endif
64 
65 /* Core OpenGL/OpenGLES functions: the following functions pointers typedefs
66  * are not defined. */
67 #if !defined(_WIN32) /* Already defined on Win32 */
68 typedef void (*PFNGLACTIVETEXTUREPROC) (GLenum texture);
69 #endif
70 typedef void (APIENTRY *PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
71 typedef void (APIENTRY *PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
72 typedef void (APIENTRY *PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
73 typedef void (APIENTRY *PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
74 typedef void (APIENTRY *PFNGLCLEARPROC) (GLbitfield mask);
75 typedef void (APIENTRY *PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
76 typedef void (APIENTRY *PFNGLDEPTHMASKPROC) (GLboolean flag);
77 typedef void (APIENTRY *PFNGLDISABLEPROC) (GLenum cap);
78 typedef void (APIENTRY *PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
79 typedef void (APIENTRY *PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
80 typedef void (APIENTRY *PFNGLENABLEPROC) (GLenum cap);
81 typedef void (APIENTRY *PFNGLFINISHPROC)(void);
82 typedef void (APIENTRY *PFNGLFLUSHPROC)(void);
83 typedef void (APIENTRY *PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
84 typedef GLenum (APIENTRY *PFNGLGETERRORPROC) (void);
85 typedef void (APIENTRY *PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
86 typedef const GLubyte *(APIENTRY *PFNGLGETSTRINGPROC) (GLenum name);
87 typedef void (APIENTRY *PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
88 typedef void (APIENTRY *PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
89 typedef void (APIENTRY *PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param);
90 typedef void (APIENTRY *PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
91 typedef void (APIENTRY *PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
92 typedef void (APIENTRY *PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
93 typedef void (APIENTRY *PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
94 typedef void (APIENTRY *PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
95 
96 /* The following are defined in glext.h but not for GLES2 or on Apple systems */
97 #if defined(USE_OPENGL_ES2) || defined(__APPLE__)
98 #   define PFNGLGETPROGRAMIVPROC             typeof(glGetProgramiv)*
99 #   define PFNGLGETPROGRAMINFOLOGPROC        typeof(glGetProgramInfoLog)*
100 #   define PFNGLGETSHADERIVPROC              typeof(glGetShaderiv)*
101 #   define PFNGLGETSHADERINFOLOGPROC         typeof(glGetShaderInfoLog)*
102 #   define PFNGLGETUNIFORMLOCATIONPROC       typeof(glGetUniformLocation)*
103 #   define PFNGLGETATTRIBLOCATIONPROC        typeof(glGetAttribLocation)*
104 #   define PFNGLVERTEXATTRIBPOINTERPROC      typeof(glVertexAttribPointer)*
105 #   define PFNGLENABLEVERTEXATTRIBARRAYPROC  typeof(glEnableVertexAttribArray)*
106 #   define PFNGLUNIFORMMATRIX4FVPROC         typeof(glUniformMatrix4fv)*
107 #   define PFNGLUNIFORMMATRIX3FVPROC         typeof(glUniformMatrix3fv)*
108 #   define PFNGLUNIFORMMATRIX2FVPROC         typeof(glUniformMatrix2fv)*
109 #   define PFNGLUNIFORM4FVPROC               typeof(glUniform4fv)*
110 #   define PFNGLUNIFORM4FPROC                typeof(glUniform4f)*
111 #   define PFNGLUNIFORM3FPROC                typeof(glUniform3f)*
112 #   define PFNGLUNIFORM2FPROC                typeof(glUniform2f)*
113 #   define PFNGLUNIFORM1FPROC                typeof(glUniform1f)*
114 #   define PFNGLUNIFORM1IPROC                typeof(glUniform1i)*
115 #   define PFNGLCREATESHADERPROC             typeof(glCreateShader)*
116 #   define PFNGLSHADERSOURCEPROC             typeof(glShaderSource)*
117 #   define PFNGLCOMPILESHADERPROC            typeof(glCompileShader)*
118 #   define PFNGLDELETESHADERPROC             typeof(glDeleteShader)*
119 #   define PFNGLCREATEPROGRAMPROC            typeof(glCreateProgram)*
120 #   define PFNGLLINKPROGRAMPROC              typeof(glLinkProgram)*
121 #   define PFNGLUSEPROGRAMPROC               typeof(glUseProgram)*
122 #   define PFNGLDELETEPROGRAMPROC            typeof(glDeleteProgram)*
123 #   define PFNGLATTACHSHADERPROC             typeof(glAttachShader)*
124 #   define PFNGLGENBUFFERSPROC               typeof(glGenBuffers)*
125 #   define PFNGLBINDBUFFERPROC               typeof(glBindBuffer)*
126 #   define PFNGLBUFFERDATAPROC               typeof(glBufferData)*
127 #   define PFNGLBUFFERSUBDATAPROC            typeof(glBufferSubData)*
128 #   define PFNGLDELETEBUFFERSPROC            typeof(glDeleteBuffers)*
129 #   define PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC typeof(glGetFramebufferAttachmentParameteriv)*
130 #if defined(__APPLE__)
131 #   import <CoreFoundation/CoreFoundation.h>
132 #endif
133 #endif
134 
135 /* The following are defined in glext.h but doesn't exist in GLES2 */
136 #if defined(USE_OPENGL_ES2) || defined(__APPLE__)
137 typedef struct __GLsync *GLsync;
138 typedef uint64_t GLuint64;
139 typedef void *(APIENTRY *PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
140 typedef void (APIENTRY *PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
141 typedef GLboolean (APIENTRY *PFNGLUNMAPBUFFERPROC) (GLenum target);
142 typedef GLsync (APIENTRY *PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
143 typedef void (APIENTRY *PFNGLDELETESYNCPROC) (GLsync sync);
144 typedef GLenum (APIENTRY *PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
145 #endif
146 
147 /**
148  * Structure containing function pointers to shaders commands
149  */
150 typedef struct {
151     /*
152      * GL / GLES core functions
153      */
154     PFNGLBINDTEXTUREPROC    BindTexture;
155     PFNGLBLENDFUNCPROC      BlendFunc;
156     PFNGLCLEARCOLORPROC     ClearColor;
157     PFNGLCLEARPROC          Clear;
158     PFNGLDELETETEXTURESPROC DeleteTextures;
159     PFNGLDEPTHMASKPROC      DepthMask;
160     PFNGLDISABLEPROC        Disable;
161     PFNGLDRAWARRAYSPROC     DrawArrays;
162     PFNGLDRAWELEMENTSPROC   DrawElements;
163     PFNGLENABLEPROC         Enable;
164     PFNGLFINISHPROC         Finish;
165     PFNGLFLUSHPROC          Flush;
166     PFNGLGENTEXTURESPROC    GenTextures;
167     PFNGLGETERRORPROC       GetError;
168     PFNGLGETINTEGERVPROC    GetIntegerv;
169     PFNGLGETSTRINGPROC      GetString;
170     PFNGLPIXELSTOREIPROC    PixelStorei;
171     PFNGLTEXIMAGE2DPROC     TexImage2D;
172     PFNGLTEXPARAMETERFPROC  TexParameterf;
173     PFNGLTEXPARAMETERIPROC  TexParameteri;
174     PFNGLTEXSUBIMAGE2DPROC  TexSubImage2D;
175     PFNGLVIEWPORTPROC       Viewport;
176 
177     /* GL only core functions: NULL for GLES2 */
178     PFNGLGETTEXLEVELPARAMETERIVPROC GetTexLevelParameteriv; /* Can be NULL */
179     PFNGLTEXENVFPROC                TexEnvf; /* Can be NULL */
180 
181     /*
182      * GL / GLES extensions
183      */
184 
185     /* Shader commands */
186     PFNGLCREATESHADERPROC   CreateShader;
187     PFNGLSHADERSOURCEPROC   ShaderSource;
188     PFNGLCOMPILESHADERPROC  CompileShader;
189     PFNGLATTACHSHADERPROC   AttachShader;
190     PFNGLDELETESHADERPROC   DeleteShader;
191 
192     /* Shader log commands */
193     PFNGLGETPROGRAMIVPROC       GetProgramiv;
194     PFNGLGETSHADERIVPROC        GetShaderiv;
195     PFNGLGETPROGRAMINFOLOGPROC  GetProgramInfoLog;
196     PFNGLGETSHADERINFOLOGPROC   GetShaderInfoLog;
197 
198     /* Shader variables commands */
199     PFNGLGETUNIFORMLOCATIONPROC      GetUniformLocation;
200     PFNGLGETATTRIBLOCATIONPROC       GetAttribLocation;
201     PFNGLVERTEXATTRIBPOINTERPROC     VertexAttribPointer;
202     PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
203     PFNGLUNIFORMMATRIX4FVPROC        UniformMatrix4fv;
204     PFNGLUNIFORMMATRIX3FVPROC        UniformMatrix3fv;
205     PFNGLUNIFORMMATRIX2FVPROC        UniformMatrix2fv;
206     PFNGLUNIFORM4FVPROC              Uniform4fv;
207     PFNGLUNIFORM4FPROC               Uniform4f;
208     PFNGLUNIFORM3FPROC               Uniform3f;
209     PFNGLUNIFORM2FPROC               Uniform2f;
210     PFNGLUNIFORM1FPROC               Uniform1f;
211     PFNGLUNIFORM1IPROC               Uniform1i;
212 
213     /* Program commands */
214     PFNGLCREATEPROGRAMPROC CreateProgram;
215     PFNGLLINKPROGRAMPROC   LinkProgram;
216     PFNGLUSEPROGRAMPROC    UseProgram;
217     PFNGLDELETEPROGRAMPROC DeleteProgram;
218 
219     /* Texture commands */
220     PFNGLACTIVETEXTUREPROC ActiveTexture;
221 
222     /* Buffers commands */
223     PFNGLGENBUFFERSPROC    GenBuffers;
224     PFNGLBINDBUFFERPROC    BindBuffer;
225     PFNGLBUFFERDATAPROC    BufferData;
226     PFNGLDELETEBUFFERSPROC DeleteBuffers;
227 
228     /* Framebuffers commands */
229     PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC GetFramebufferAttachmentParameteriv;
230 
231     /* Commands used for PBO and/or Persistent mapping */
232     PFNGLBUFFERSUBDATAPROC          BufferSubData; /* can be NULL */
233     PFNGLBUFFERSTORAGEPROC          BufferStorage; /* can be NULL */
234     PFNGLMAPBUFFERRANGEPROC         MapBufferRange; /* can be NULL */
235     PFNGLFLUSHMAPPEDBUFFERRANGEPROC FlushMappedBufferRange; /* can be NULL */
236     PFNGLUNMAPBUFFERPROC            UnmapBuffer; /* can be NULL */
237     PFNGLFENCESYNCPROC              FenceSync; /* can be NULL */
238     PFNGLDELETESYNCPROC             DeleteSync; /* can be NULL */
239     PFNGLCLIENTWAITSYNCPROC         ClientWaitSync; /* can be NULL */
240 } opengl_vtable_t;
241 
HasExtension(const char * apis,const char * api)242 static inline bool HasExtension(const char *apis, const char *api)
243 {
244     size_t apilen = strlen(api);
245     while (apis) {
246         while (*apis == ' ')
247             apis++;
248         if (!strncmp(apis, api, apilen) && memchr(" ", apis[apilen], 2))
249             return true;
250         apis = strchr(apis, ' ');
251     }
252     return false;
253 }
254 
255 struct pl_context;
256 struct pl_shader;
257 struct pl_shader_res;
258 
259 /*
260  * Structure that is filled by "glhw converter" module probe function
261  * The implementation should initialize every members of the struct that are
262  * not set by the caller
263  */
264 typedef struct opengl_tex_converter_t opengl_tex_converter_t;
265 struct opengl_tex_converter_t
266 {
267     VLC_COMMON_MEMBERS
268 
269     module_t *p_module;
270 
271     /* Pointer to object gl, set by the caller */
272     vlc_gl_t *gl;
273 
274     /* libplacebo context, created by the caller (optional) */
275     struct pl_context *pl_ctx;
276 
277     /* Function pointers to OpenGL functions, set by the caller */
278     const opengl_vtable_t *vt;
279 
280     /* True to dump shaders, set by the caller */
281     bool b_dump_shaders;
282 
283     /* Function pointer to the shader init command, set by the caller, see
284      * opengl_fragment_shader_init() documentation. */
285     GLuint (*pf_fragment_shader_init)(opengl_tex_converter_t *, GLenum,
286                                       vlc_fourcc_t, video_color_space_t);
287 
288     /* Available gl extensions (from GL_EXTENSIONS) */
289     const char *glexts;
290 
291     /* True if the current API is OpenGL ES, set by the caller */
292     bool is_gles;
293     /* GLSL version, set by the caller. 100 for GLSL ES, 120 for desktop GLSL */
294     unsigned glsl_version;
295     /* Precision header, set by the caller. In OpenGLES, the fragment language
296      * has no default precision qualifier for floating point types. */
297     const char *glsl_precision_header;
298 
299     /* Can only be changed from the module open function */
300     video_format_t fmt;
301 
302     /* Fragment shader, must be set from the module open function. It will be
303      * deleted by the caller. */
304     GLuint fshader;
305 
306     /* Number of textures, cannot be 0 */
307     unsigned tex_count;
308 
309     /* Texture mapping (usually: GL_TEXTURE_2D), cannot be 0 */
310     GLenum tex_target;
311 
312     /* Set to true if textures are generated from pf_update() */
313     bool handle_texs_gen;
314 
315     struct opengl_tex_cfg {
316         /* Texture scale factor, cannot be 0 */
317         vlc_rational_t w;
318         vlc_rational_t h;
319 
320         /* The following is used and filled by the opengl_fragment_shader_init
321          * function. */
322         GLint  internal;
323         GLenum format;
324         GLenum type;
325     } texs[PICTURE_PLANE_MAX];
326 
327     /* The following is used and filled by the opengl_fragment_shader_init
328      * function. */
329     struct {
330         GLint Texture[PICTURE_PLANE_MAX];
331         GLint TexSize[PICTURE_PLANE_MAX]; /* for GL_TEXTURE_RECTANGLE */
332         GLint Coefficients;
333         GLint FillColor;
334         GLint *pl_vars; /* for pl_sh_res */
335     } uloc;
336     bool yuv_color;
337     GLfloat yuv_coefficients[16];
338 
339     struct pl_shader *pl_sh;
340     const struct pl_shader_res *pl_sh_res;
341 
342     /* Private context */
343     void *priv;
344 
345     /*
346      * Callback to allocate data for bound textures
347      *
348      * This function pointer can be NULL. Software converters should call
349      * glTexImage2D() to allocate textures data (it will be deallocated by the
350      * caller when calling glDeleteTextures()). Won't be called if
351      * handle_texs_gen is true.
352      *
353      * \param fc OpenGL tex converter
354      * \param textures array of textures to bind (one per plane)
355      * \param tex_width array of tex width (one per plane)
356      * \param tex_height array of tex height (one per plane)
357      * \return VLC_SUCCESS or a VLC error
358      */
359     int (*pf_allocate_textures)(const opengl_tex_converter_t *tc, GLuint *textures,
360                                 const GLsizei *tex_width, const GLsizei *tex_height);
361 
362     /*
363      * Callback to allocate a picture pool
364      *
365      * This function pointer *can* be NULL. If NULL, A generic pool with
366      * pictures allocated from the video_format_t will be used.
367      *
368      * \param fc OpenGL tex converter
369      * \param requested_count number of pictures to allocate
370      * \return the picture pool or NULL in case of error
371      */
372     picture_pool_t *(*pf_get_pool)(const opengl_tex_converter_t *fc,
373                                    unsigned requested_count);
374 
375     /*
376      * Callback to update a picture
377      *
378      * This function pointer cannot be NULL. The implementation should upload
379      * every planes of the picture.
380      *
381      * \param fc OpenGL tex converter
382      * \param textures array of textures to bind (one per plane)
383      * \param tex_width array of tex width (one per plane)
384      * \param tex_height array of tex height (one per plane)
385      * \param pic picture to update
386      * \param plane_offset offsets of each picture planes to read data from
387      * (one per plane, can be NULL)
388      * \return VLC_SUCCESS or a VLC error
389      */
390     int (*pf_update)(const opengl_tex_converter_t *fc, GLuint *textures,
391                      const GLsizei *tex_width, const GLsizei *tex_height,
392                      picture_t *pic, const size_t *plane_offset);
393 
394     /*
395      * Callback to fetch locations of uniform or attributes variables
396      *
397      * This function pointer cannot be NULL. This callback is called one time
398      * after init.
399      *
400      * \param fc OpenGL tex converter
401      * \param program linked program that will be used by this tex converter
402      * \return VLC_SUCCESS or a VLC error
403      */
404     int (*pf_fetch_locations)(opengl_tex_converter_t *fc, GLuint program);
405 
406     /*
407      * Callback to prepare the fragment shader
408      *
409      * This function pointer cannot be NULL. This callback can be used to
410      * specify values of uniform variables.
411      *
412      * \param fc OpenGL tex converter
413      * \param tex_width array of tex width (one per plane)
414      * \param tex_height array of tex height (one per plane)
415      * \param alpha alpha value, used only for RGBA fragment shader
416      */
417     void (*pf_prepare_shader)(const opengl_tex_converter_t *fc,
418                               const GLsizei *tex_width, const GLsizei *tex_height,
419                               float alpha);
420 };
421 
422 /*
423  * Generate a fragment shader
424  *
425  * This utility function can be used by hw opengl tex converters that need a
426  * generic fragment shader. It will compile a fragment shader generated from
427  * the chroma and the tex target. This will initialize all elements of the
428  * opengl_tex_converter_t struct except for priv, pf_allocate_texture,
429  * pf_get_pool, pf_update
430  *
431  * \param tc OpenGL tex converter
432  * \param tex_target GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE
433  * \param chroma chroma used to generate the fragment shader
434  * \param if not COLOR_SPACE_UNDEF, YUV planes will be converted to RGB
435  * according to the color space
436  * \return the compiled fragment shader or 0 in case of error
437  */
438 static inline GLuint
opengl_fragment_shader_init(opengl_tex_converter_t * tc,GLenum tex_target,vlc_fourcc_t chroma,video_color_space_t yuv_space)439 opengl_fragment_shader_init(opengl_tex_converter_t *tc, GLenum tex_target,
440                             vlc_fourcc_t chroma, video_color_space_t yuv_space)
441 {
442     return tc->pf_fragment_shader_init(tc, tex_target, chroma, yuv_space);
443 }
444 
445 #endif /* include-guard */
446