654dd4cad414f5c6d83a4761489891a3e986a608
[platform/upstream/gstreamer.git] / gst-libs / gst / gl / x11 / gstglwindow_x11_glx.c
1 /*
2  * GStreamer
3  * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com>
4  * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #define GLIB_DISABLE_DEPRECATION_WARNINGS
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <gst/gst.h>
29
30 #include "gstglwindow_x11_glx.h"
31
32 #define GST_CAT_DEFAULT gst_gl_window_debug
33
34 #define gst_gl_window_x11_glx_parent_class parent_class
35 G_DEFINE_TYPE (GstGLWindowX11GLX, gst_gl_window_x11_glx,
36     GST_GL_TYPE_WINDOW_X11);
37
38 static guintptr gst_gl_window_x11_glx_get_gl_context (GstGLWindowX11 *
39     window_x11);
40 static void gst_gl_window_x11_glx_swap_buffers (GstGLWindowX11 * window_x11);
41 static gboolean gst_gl_window_x11_glx_activate (GstGLWindowX11 * window_x11,
42     gboolean activate);
43 static gboolean gst_gl_window_x11_glx_create_context (GstGLWindowX11 *
44     window_x11, GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
45 static void gst_gl_window_x11_glx_destroy_context (GstGLWindowX11 * window_x11);
46 static gboolean gst_gl_window_x11_glx_choose_format (GstGLWindowX11 *
47     window_x11, GError ** error);
48 GstGLAPI gst_gl_window_x11_glx_get_gl_api (GstGLWindow * window);
49
50 static void
51 gst_gl_window_x11_glx_class_init (GstGLWindowX11GLXClass * klass)
52 {
53   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
54   GstGLWindowX11Class *window_x11_class = (GstGLWindowX11Class *) klass;
55
56   window_x11_class->get_gl_context =
57       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_get_gl_context);
58   window_x11_class->activate =
59       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_activate);
60   window_x11_class->create_context =
61       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_create_context);
62   window_x11_class->destroy_context =
63       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_destroy_context);
64   window_x11_class->choose_format =
65       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_choose_format);
66   window_x11_class->swap_buffers =
67       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_swap_buffers);
68
69   window_class->get_gl_api =
70       GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_get_gl_api);
71 }
72
73 static void
74 gst_gl_window_x11_glx_init (GstGLWindowX11GLX * window)
75 {
76 }
77
78 /* Must be called in the gl thread */
79 GstGLWindowX11GLX *
80 gst_gl_window_x11_glx_new (GstGLAPI gl_api, guintptr external_gl_context,
81     GError ** error)
82 {
83   GstGLWindowX11GLX *window = g_object_new (GST_GL_TYPE_WINDOW_X11_GLX, NULL);
84
85   gst_gl_window_x11_open_device (GST_GL_WINDOW_X11 (window), gl_api,
86       external_gl_context, error);
87
88   return window;
89 }
90
91 static gboolean
92 gst_gl_window_x11_glx_create_context (GstGLWindowX11 * window_x11,
93     GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
94 {
95   GstGLWindowX11GLX *window_glx;
96
97   window_glx = GST_GL_WINDOW_X11_GLX (window_x11);
98
99   window_glx->glx_context =
100       glXCreateContext (window_x11->device, window_x11->visual_info,
101       (GLXContext) external_gl_context, TRUE);
102
103   if (!window_glx->glx_context) {
104     g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT,
105         "Failed to create opengl context (glXCreateContext failed)");
106     goto failure;
107   }
108
109   GST_LOG ("gl context id: %ld", (gulong) window_glx->glx_context);
110
111   return TRUE;
112
113 failure:
114   return FALSE;
115 }
116
117 static void
118 gst_gl_window_x11_glx_destroy_context (GstGLWindowX11 * window_x11)
119 {
120   GstGLWindowX11GLX *window_glx;
121
122   window_glx = GST_GL_WINDOW_X11_GLX (window_x11);
123
124   glXDestroyContext (window_x11->device, window_glx->glx_context);
125
126   window_glx->glx_context = 0;
127 }
128
129 static gboolean
130 gst_gl_window_x11_glx_choose_format (GstGLWindowX11 * window_x11,
131     GError ** error)
132 {
133   gint error_base;
134   gint event_base;
135
136   gint attrib[] = {
137     GLX_RGBA,
138     GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
139     GLX_DEPTH_SIZE, 16,
140     GLX_DOUBLEBUFFER,
141     None
142   };
143
144   if (!glXQueryExtension (window_x11->device, &error_base, &event_base)) {
145     g_set_error (error, GST_GL_WINDOW_ERROR,
146         GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, "No GLX extension");
147     goto failure;
148   }
149
150   window_x11->visual_info = glXChooseVisual (window_x11->device,
151       window_x11->screen_num, attrib);
152
153   if (!window_x11->visual_info) {
154     g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG,
155         "Bad attributes in glXChooseVisual");
156     goto failure;
157   }
158
159   return TRUE;
160
161 failure:
162   return FALSE;
163 }
164
165 static void
166 gst_gl_window_x11_glx_swap_buffers (GstGLWindowX11 * window_x11)
167 {
168   glXSwapBuffers (window_x11->device, window_x11->internal_win_id);
169 }
170
171 static guintptr
172 gst_gl_window_x11_glx_get_gl_context (GstGLWindowX11 * window_x11)
173 {
174   return (guintptr) GST_GL_WINDOW_X11_GLX (window_x11)->glx_context;
175 }
176
177 static gboolean
178 gst_gl_window_x11_glx_activate (GstGLWindowX11 * window_x11, gboolean activate)
179 {
180   gboolean result;
181
182   if (activate) {
183     result = glXMakeCurrent (window_x11->device, window_x11->internal_win_id,
184         GST_GL_WINDOW_X11_GLX (window_x11)->glx_context);
185   } else {
186     result = glXMakeCurrent (window_x11->device, None, NULL);
187   }
188
189   return result;
190 }
191
192 GstGLAPI
193 gst_gl_window_x11_glx_get_gl_api (GstGLWindow * window)
194 {
195   return GST_GL_API_OPENGL;
196 }