2 * gstvaapitexture_glx.c - VA/GLX texture abstraction
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6 * Copyright (C) 2012-2014 Intel Corporation
7 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
26 * SECTION:gstvaapitexture_glx
27 * @short_description: VA/GLX texture abstraction
31 #include "gstvaapitexture.h"
32 #include "gstvaapitexture_glx.h"
33 #include "gstvaapitexture_priv.h"
34 #include "gstvaapisurface_priv.h"
35 #include "gstvaapicompat.h"
36 #include "gstvaapiutils.h"
37 #include "gstvaapiutils_glx.h"
38 #include "gstvaapidisplay_glx.h"
39 #include "gstvaapidisplay_x11_priv.h"
40 #include "gstvaapidisplay_glx_priv.h"
43 #include "gstvaapidebug.h"
45 #define GST_VAAPI_TEXTURE_GLX(texture) \
46 ((GstVaapiTextureGLX *)(texture))
48 typedef struct _GstVaapiTextureGLXPrivate GstVaapiTextureGLXPrivate;
51 * GstVaapiTextureGLXPrivate:
53 * GLX texture specific fields.
55 struct _GstVaapiTextureGLXPrivate
58 GstVaapiTexture *texture;
59 GLContextState *gl_context;
61 GLFramebufferObject *fbo;
65 gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture,
66 GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect,
70 destroy_objects (GstVaapiTextureGLXPrivate * texture)
72 GLContextState old_cs;
74 if (texture->gl_context)
75 gl_set_current_context (texture->gl_context, &old_cs);
78 gl_destroy_framebuffer_object (texture->fbo);
83 gl_destroy_pixmap_object (texture->pixo);
87 if (texture->gl_context) {
88 gl_set_current_context (&old_cs, NULL);
89 gl_destroy_context (texture->gl_context);
90 texture->gl_context = NULL;
95 destroy_texture_unlocked (GstVaapiTextureGLXPrivate * texture_glx)
97 GstVaapiTexture *texture = texture_glx->texture;
98 const guint texture_id = GST_VAAPI_TEXTURE_ID (texture);
100 destroy_objects (texture_glx);
103 if (!texture->is_wrapped)
104 glDeleteTextures (1, &texture_id);
105 GST_VAAPI_TEXTURE_ID (texture) = 0;
110 gst_vaapi_texture_glx_destroy (GstVaapiTextureGLXPrivate * texture_glx)
112 GstVaapiTexture *texture = texture_glx->texture;
114 GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
115 destroy_texture_unlocked (texture_glx);
116 GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
118 g_free (texture_glx);
122 create_objects (GstVaapiTexture * texture, guint texture_id)
124 GstVaapiTextureGLXPrivate *texture_glx =
125 gst_vaapi_texture_get_private (texture);
127 GST_VAAPI_DISPLAY_NATIVE (GST_VAAPI_TEXTURE_DISPLAY (texture));
128 GLContextState old_cs;
129 gboolean success = FALSE;
131 gl_get_current_context (&old_cs);
133 texture_glx->gl_context =
134 gl_create_context (dpy, DefaultScreen (dpy), &old_cs);
135 if (!texture_glx->gl_context
136 || !gl_set_current_context (texture_glx->gl_context, NULL))
139 texture_glx->pixo = gl_create_pixmap_object (dpy,
140 texture->width, texture->height);
141 if (!texture_glx->pixo) {
142 GST_ERROR ("failed to create GLX pixmap");
143 goto out_reset_context;
146 texture_glx->fbo = gl_create_framebuffer_object (texture->gl_target,
147 texture_id, texture->width, texture->height);
148 if (!texture_glx->fbo) {
149 GST_ERROR ("failed to create FBO");
150 goto out_reset_context;
155 gl_set_current_context (&old_cs, NULL);
160 create_texture_unlocked (GstVaapiTexture * texture)
164 if (texture->is_wrapped)
165 texture_id = GST_VAAPI_TEXTURE_ID (texture);
167 texture_id = gl_create_texture (texture->gl_target, texture->gl_format,
168 texture->width, texture->height);
171 GST_VAAPI_TEXTURE_ID (texture) = texture_id;
173 return create_objects (texture, texture_id);
177 gst_vaapi_texture_glx_create (GstVaapiTexture * texture)
181 GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
182 success = create_texture_unlocked (texture);
183 GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
188 static GstVaapiTexture *
189 gst_vaapi_texture_glx_new_internal (GstVaapiTexture * texture)
191 GstVaapiTextureGLXPrivate *texture_glx;
193 texture->put_surface = gst_vaapi_texture_glx_put_surface;
195 texture_glx = g_malloc0 (sizeof (GstVaapiTextureGLXPrivate));
197 gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
200 texture_glx->texture = texture;
201 gst_vaapi_texture_set_private (texture, texture_glx,
202 (GDestroyNotify) gst_vaapi_texture_glx_destroy);
204 if (!gst_vaapi_texture_glx_create (texture)) {
205 gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
213 * gst_vaapi_texture_glx_new:
214 * @display: a #GstVaapiDisplay
215 * @target: the target to which the texture is bound
216 * @format: the format of the pixel data
217 * @width: the requested width, in pixels
218 * @height: the requested height, in pixels
220 * Creates a texture with the specified dimensions, @target and
221 * @format. Note that only GL_TEXTURE_2D @target and GL_RGBA or
222 * GL_BGRA formats are supported at this time.
224 * The application shall maintain the live GL context itself. That is,
225 * gst_vaapi_window_glx_make_current() must be called beforehand, or
226 * any other function like glXMakeCurrent() if the context is managed
227 * outside of this library.
229 * Return value: the newly created #GstVaapiTexture object
232 gst_vaapi_texture_glx_new (GstVaapiDisplay * display, guint target,
233 guint format, guint width, guint height)
235 GstVaapiTexture *texture;
237 g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL);
239 texture = gst_vaapi_texture_new_internal (display, GST_VAAPI_ID_INVALID,
240 target, format, width, height);
244 return gst_vaapi_texture_glx_new_internal (texture);
247 /* Can we assume that the vsink/app context API won't change ever? */
249 gl_get_curent_api_once ()
251 static GstVaapiGLApi cur_api = GST_VAAPI_GL_API_NONE;
252 static gsize _init = 0;
254 if (g_once_init_enter (&_init)) {
255 cur_api = gl_get_current_api (NULL, NULL);
256 g_once_init_leave (&_init, 1);
263 * gst_vaapi_texture_glx_new_wrapped:
264 * @display: a #GstVaapiDisplay
265 * @texture_id: the foreign GL texture name to use
266 * @target: the target to which the texture is bound
267 * @format: the format of the pixel data
269 * Creates a texture from an existing GL texture, with the specified
270 * @target and @format. Note that only GL_TEXTURE_2D @target and
271 * GL_RGBA or GL_BGRA formats are supported at this time. The
272 * dimensions will be retrieved from the @texture_id.
274 * The application shall maintain the live GL context itself. That is,
275 * gst_vaapi_window_glx_make_current() must be called beforehand, or
276 * any other function like glXMakeCurrent() if the context is managed
277 * outside of this library.
279 * Return value: the newly created #GstVaapiTexture object
282 gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display,
283 guint texture_id, guint target, guint format)
285 guint width, height, border_width = 0;
286 GLTextureState ts = { 0, };
288 GstVaapiGLApi gl_api;
289 GstVaapiTexture *texture;
291 g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL);
292 g_return_val_if_fail (texture_id != GL_NONE, NULL);
293 g_return_val_if_fail (target == GL_TEXTURE_2D, NULL);
294 g_return_val_if_fail (format == GL_RGBA || format == GL_BGRA, NULL);
296 gl_api = gl_get_curent_api_once ();
297 if (gl_api != GST_VAAPI_GL_API_OPENGL && gl_api != GST_VAAPI_GL_API_OPENGL3)
300 /* Check texture dimensions */
301 GST_VAAPI_DISPLAY_LOCK (display);
302 if (gl_api == GST_VAAPI_GL_API_OPENGL)
303 success = gl_bind_texture (&ts, target, texture_id);
305 success = gl3_bind_texture_2d (&ts, target, texture_id);
308 if (!gl_get_texture_param (target, GL_TEXTURE_WIDTH, &width) ||
309 !gl_get_texture_param (target, GL_TEXTURE_HEIGHT, &height))
311 if (success && gl_api == GST_VAAPI_GL_API_OPENGL)
312 success = gl_get_texture_param (target, GL_TEXTURE_BORDER, &border_width);
313 gl_unbind_texture (&ts);
315 GST_VAAPI_DISPLAY_UNLOCK (display);
319 width -= 2 * border_width;
320 height -= 2 * border_width;
321 g_return_val_if_fail (width > 0, NULL);
322 g_return_val_if_fail (height > 0, NULL);
324 texture = gst_vaapi_texture_new_internal (display, texture_id, target,
325 format, width, height);
329 return gst_vaapi_texture_glx_new_internal (texture);
333 * gst_vaapi_texture_put_surface:
334 * @texture: a #GstVaapiTexture
335 * @surface: a #GstVaapiSurface
336 * @flags: postprocessing flags. See #GstVaapiTextureRenderFlags
338 * Renders the @surface into the àtexture. The @flags specify how
339 * de-interlacing (if needed), color space conversion, scaling and
340 * other postprocessing transformations are performed.
342 * Return value: %TRUE on success
345 gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * texture,
346 GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
348 GstVaapiTextureGLXPrivate *texture_glx =
349 gst_vaapi_texture_get_private (texture);
351 GLContextState old_cs;
352 gboolean success = FALSE;
354 const GLfloat *txc, *tyc;
355 static const GLfloat g_texcoords[2][2] = {
360 status = vaPutSurface (GST_VAAPI_DISPLAY_VADISPLAY (GST_VAAPI_TEXTURE_DISPLAY
361 (texture)), GST_VAAPI_SURFACE_ID (surface), texture_glx->pixo->pixmap,
362 crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height, 0, 0,
363 texture->width, texture->height, NULL, 0,
364 from_GstVaapiSurfaceRenderFlags (flags));
365 if (!vaapi_check_status (status, "vaPutSurface() [TFP]"))
368 if (texture_glx->gl_context &&
369 !gl_set_current_context (texture_glx->gl_context, &old_cs))
372 if (!gl_bind_framebuffer_object (texture_glx->fbo)) {
373 GST_ERROR ("failed to bind FBO");
374 goto out_reset_context;
377 if (!gst_vaapi_surface_sync (surface)) {
378 GST_ERROR ("failed to render surface to pixmap");
382 if (!gl_bind_pixmap_object (texture_glx->pixo)) {
383 GST_ERROR ("could not bind GLX pixmap");
387 flags = GST_MINI_OBJECT_FLAGS (texture);
388 txc = g_texcoords[! !(flags & GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED)];
389 tyc = g_texcoords[! !(flags & GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED)];
391 glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
394 glTexCoord2f (txc[0], tyc[0]);
396 glTexCoord2f (txc[0], tyc[1]);
397 glVertex2i (0, texture->height);
398 glTexCoord2f (txc[1], tyc[1]);
399 glVertex2i (texture->width, texture->height);
400 glTexCoord2f (txc[1], tyc[0]);
401 glVertex2i (texture->width, 0);
405 if (!gl_unbind_pixmap_object (texture_glx->pixo)) {
406 GST_ERROR ("failed to release GLX pixmap");
412 if (!gl_unbind_framebuffer_object (texture_glx->fbo))
415 if (texture_glx->gl_context && !gl_set_current_context (&old_cs, NULL))
421 gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture,
422 GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
426 GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
427 success = gst_vaapi_texture_glx_put_surface_unlocked (texture, surface,
429 GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));