From: Gwenole Beauchesne Date: Thu, 23 Oct 2014 15:44:23 +0000 (+0200) Subject: texture: move to core libgstvaapi base library. X-Git-Tag: 1.19.3~503^2~1945 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2101685b7d5f02d05665e85c0ed6d0788a3d25f5;p=platform%2Fupstream%2Fgstreamer.git texture: move to core libgstvaapi base library. GstVaapiTexture is a generic abstraction that could be moved to the core libgstvaapi library. While doing this, no extra dependency needs to be added. This means that a GstVaapitextureClass is now available for any specific code that needs to be added, e.g. creation of the underlying GL texture objects, or backend dependent ways to upload a surface to the texture object. Generic OpenGL data types (GLuint, GLenum) are also replaced with a plain guint. https://bugzilla.gnome.org/show_bug.cgi?id=736715 --- diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am index 9c5cf88..e0b9fd4 100644 --- a/gst-libs/gst/vaapi/Makefile.am +++ b/gst-libs/gst/vaapi/Makefile.am @@ -70,6 +70,7 @@ libgstvaapi_source_c = \ gstvaapisurface.c \ gstvaapisurfacepool.c \ gstvaapisurfaceproxy.c \ + gstvaapitexture.c \ gstvaapiutils.c \ gstvaapiutils_core.c \ gstvaapiutils_h264.c \ @@ -97,6 +98,7 @@ libgstvaapi_source_h = \ gstvaapisurface.h \ gstvaapisurfacepool.h \ gstvaapisurfaceproxy.h \ + gstvaapitexture.h \ gstvaapitypes.h \ gstvaapiutils_h264.h \ gstvaapiutils_mpeg2.h \ @@ -127,6 +129,7 @@ libgstvaapi_source_priv_h = \ gstvaapipixmap_priv.h \ gstvaapisurface_priv.h \ gstvaapisurfaceproxy_priv.h \ + gstvaapitexture_priv.h \ gstvaapiutils.h \ gstvaapiutils_core.h \ gstvaapiutils_h264_priv.h \ @@ -227,7 +230,7 @@ libgstvaapi_x11_source_priv_h = \ libgstvaapi_glx_source_c = \ gstvaapidisplay_glx.c \ - gstvaapitexture.c \ + gstvaapitexture_glx.c \ gstvaapiutils.c \ gstvaapiutils_glx.c \ gstvaapiutils_x11.c \ diff --git a/gst-libs/gst/vaapi/gstvaapitexture.c b/gst-libs/gst/vaapi/gstvaapitexture.c index 77ef95f..4d0df1c 100644 --- a/gst-libs/gst/vaapi/gstvaapitexture.c +++ b/gst-libs/gst/vaapi/gstvaapitexture.c @@ -29,258 +29,52 @@ #include "sysdeps.h" #include "gstvaapitexture.h" -#include "gstvaapicompat.h" -#include "gstvaapiutils.h" -#include "gstvaapiutils_glx.h" -#include "gstvaapidisplay_glx.h" -#include "gstvaapidisplay_x11_priv.h" -#include "gstvaapidisplay_glx_priv.h" -#include "gstvaapiobject_priv.h" +#include "gstvaapitexture_priv.h" #define DEBUG 1 #include "gstvaapidebug.h" -typedef struct _GstVaapiTextureClass GstVaapiTextureClass; - -/** - * GstVaapiTexture: - * - * Base object for system-dependent textures. - */ -struct _GstVaapiTexture -{ - /*< private >*/ - GstVaapiObject parent_instance; - - GLenum target; - GLenum format; - guint width; - guint height; - GLContextState *gl_context; - void *gl_surface; - GLPixmapObject *pixo; - GLFramebufferObject *fbo; - guint foreign_texture:1; -}; - -/** - * GstVaapiTextureClass: - * - * Base class for system-dependent textures. - */ -struct _GstVaapiTextureClass -{ - GstVaapiObjectClass parent_class; -}; - -static void -_gst_vaapi_texture_destroy_objects (GstVaapiTexture * texture) -{ - GLContextState old_cs; - - GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); - if (texture->gl_context) - gl_set_current_context (texture->gl_context, &old_cs); - - if (texture->fbo) { - gl_destroy_framebuffer_object (texture->fbo); - texture->fbo = NULL; - } - - if (texture->pixo) { - gl_destroy_pixmap_object (texture->pixo); - texture->pixo = NULL; - } - - if (texture->gl_context) { - gl_set_current_context (&old_cs, NULL); - gl_destroy_context (texture->gl_context); - texture->gl_context = NULL; - } - GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); -} - -static void -gst_vaapi_texture_destroy (GstVaapiTexture * texture) -{ - const GLuint texture_id = GST_VAAPI_OBJECT_ID (texture); - - _gst_vaapi_texture_destroy_objects (texture); - - if (texture_id) { - if (!texture->foreign_texture) - glDeleteTextures (1, &texture_id); - GST_VAAPI_OBJECT_ID (texture) = 0; - } -} - -static gboolean -_gst_vaapi_texture_create_objects (GstVaapiTexture * texture, GLuint texture_id) -{ - gboolean success = FALSE; - GLContextState old_cs; - - GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); - gl_get_current_context (&old_cs); - texture->gl_context = gl_create_context (GST_VAAPI_OBJECT_XDISPLAY (texture), - GST_VAAPI_OBJECT_XSCREEN (texture), &old_cs); - if (!texture->gl_context || - !gl_set_current_context (texture->gl_context, NULL)) - goto end; - - texture->pixo = gl_create_pixmap_object (GST_VAAPI_OBJECT_XDISPLAY (texture), - texture->width, texture->height); - if (!texture->pixo) - goto end; - - texture->fbo = gl_create_framebuffer_object (texture->target, - texture_id, texture->width, texture->height); - if (texture->fbo) - success = TRUE; -end: - gl_set_current_context (&old_cs, NULL); - GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); - return success; -} - -static gboolean -gst_vaapi_texture_create (GstVaapiTexture * texture) -{ - GLuint texture_id; - - if (texture->foreign_texture) - texture_id = GST_VAAPI_OBJECT_ID (texture); - else { - GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); - texture_id = gl_create_texture (texture->target, - texture->format, texture->width, texture->height); - GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); - if (!texture_id) - return FALSE; - GST_VAAPI_OBJECT_ID (texture) = texture_id; - } - - return _gst_vaapi_texture_create_objects (texture, texture_id); -} +/* Ensure those symbols are actually defined in the resulting libraries */ +#undef gst_vaapi_texture_ref +#undef gst_vaapi_texture_unref +#undef gst_vaapi_texture_replace static void -gst_vaapi_texture_init (GstVaapiTexture * texture, GLuint texture_id, - GLenum target, GLenum format, guint width, guint height) +gst_vaapi_texture_init (GstVaapiTexture * texture, guint texture_id, + guint target, guint format, guint width, guint height) { GST_VAAPI_OBJECT_ID (texture) = texture_id; - texture->foreign_texture = texture_id != GL_NONE; - - texture->target = target; - texture->format = format; + texture->is_wrapped = texture_id != 0; + texture->gl_target = target; + texture->gl_format = format; texture->width = width; texture->height = height; } -#define gst_vaapi_texture_finalize gst_vaapi_texture_destroy -GST_VAAPI_OBJECT_DEFINE_CLASS (GstVaapiTexture, gst_vaapi_texture); - -/** - * gst_vaapi_texture_new: - * @display: a #GstVaapiDisplay - * @target: the target to which the texture is bound - * @format: the format of the pixel data - * @width: the requested width, in pixels - * @height: the requested height, in pixels - * - * Creates a texture with the specified dimensions, @target and - * @format. Note that only GL_TEXTURE_2D @target and GL_RGBA or - * GL_BGRA formats are supported at this time. - * - * The application shall maintain the live GL context itself. That is, - * gst_vaapi_window_glx_make_current() must be called beforehand, or - * any other function like glXMakeCurrent() if the context is managed - * outside of this library. - * - * Return value: the newly created #GstVaapiTexture object - */ -GstVaapiTexture * -gst_vaapi_texture_new (GstVaapiDisplay * display, GLenum target, GLenum format, - guint width, guint height) +static inline gboolean +gst_vaapi_texture_allocate (GstVaapiTexture * texture) { - GstVaapiTexture *texture; - - g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); - g_return_val_if_fail (target != GL_NONE, NULL); - g_return_val_if_fail (format != GL_NONE, NULL); - g_return_val_if_fail (width > 0, NULL); - g_return_val_if_fail (height > 0, NULL); - - texture = gst_vaapi_object_new (gst_vaapi_texture_class (), display); - if (!texture) - return NULL; - - gst_vaapi_texture_init (texture, GL_NONE, target, format, width, height); - if (!gst_vaapi_texture_create (texture)) - goto error; - return texture; - -error: - gst_vaapi_object_unref (texture); - return NULL; + return GST_VAAPI_TEXTURE_GET_CLASS (texture)->allocate (texture); } -/** - * gst_vaapi_texture_new_with_texture: - * @display: a #GstVaapiDisplay - * @texture_id: the foreign GL texture name to use - * @target: the target to which the texture is bound - * @format: the format of the pixel data - * - * Creates a texture from an existing GL texture, with the specified - * @target and @format. Note that only GL_TEXTURE_2D @target and - * GL_RGBA or GL_BGRA formats are supported at this time. The - * dimensions will be retrieved from the @texture_id. - * - * The application shall maintain the live GL context itself. That is, - * gst_vaapi_window_glx_make_current() must be called beforehand, or - * any other function like glXMakeCurrent() if the context is managed - * outside of this library. - * - * Return value: the newly created #GstVaapiTexture object - */ GstVaapiTexture * -gst_vaapi_texture_new_with_texture (GstVaapiDisplay * display, - GLuint texture_id, GLenum target, GLenum format) +gst_vaapi_texture_new (const GstVaapiTextureClass * klass, + GstVaapiDisplay * display, guint texture_id, guint target, guint format, + guint width, guint height) { GstVaapiTexture *texture; - guint width, height, border_width; - GLTextureState ts; - gboolean success; - g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); - g_return_val_if_fail (target != GL_NONE, NULL); - g_return_val_if_fail (format != GL_NONE, NULL); - - /* Check texture dimensions */ - GST_VAAPI_DISPLAY_LOCK (display); - success = gl_bind_texture (&ts, target, texture_id); - if (success) { - if (!gl_get_texture_param (target, GL_TEXTURE_WIDTH, &width) || - !gl_get_texture_param (target, GL_TEXTURE_HEIGHT, &height) || - !gl_get_texture_param (target, GL_TEXTURE_BORDER, &border_width)) - success = FALSE; - gl_unbind_texture (&ts); - } - GST_VAAPI_DISPLAY_UNLOCK (display); - if (!success) - return NULL; - - width -= 2 * border_width; - height -= 2 * border_width; + g_return_val_if_fail (target != 0, NULL); + g_return_val_if_fail (format != 0, NULL); g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (height > 0, NULL); - texture = gst_vaapi_object_new (gst_vaapi_texture_class (), display); + texture = gst_vaapi_object_new (GST_VAAPI_OBJECT_CLASS (klass), display); if (!texture) return NULL; gst_vaapi_texture_init (texture, texture_id, target, format, width, height); - if (!gst_vaapi_texture_create (texture)) + if (!gst_vaapi_texture_allocate (texture)) goto error; return texture; @@ -300,7 +94,7 @@ error: GstVaapiTexture * gst_vaapi_texture_ref (GstVaapiTexture * texture) { - return gst_vaapi_object_ref (texture); + return gst_vaapi_texture_ref_internal (texture); } /** @@ -313,7 +107,7 @@ gst_vaapi_texture_ref (GstVaapiTexture * texture) void gst_vaapi_texture_unref (GstVaapiTexture * texture) { - gst_vaapi_object_unref (texture); + gst_vaapi_texture_unref_internal (texture); } /** @@ -329,7 +123,7 @@ void gst_vaapi_texture_replace (GstVaapiTexture ** old_texture_ptr, GstVaapiTexture * new_texture) { - gst_vaapi_object_replace (old_texture_ptr, new_texture); + gst_vaapi_texture_replace_internal (old_texture_ptr, new_texture); } /** @@ -340,12 +134,12 @@ gst_vaapi_texture_replace (GstVaapiTexture ** old_texture_ptr, * * Return value: the underlying texture id of the @texture */ -GLuint +guint gst_vaapi_texture_get_id (GstVaapiTexture * texture) { g_return_val_if_fail (texture != NULL, 0); - return GST_VAAPI_OBJECT_ID (texture); + return GST_VAAPI_TEXTURE_ID (texture); } /** @@ -356,12 +150,12 @@ gst_vaapi_texture_get_id (GstVaapiTexture * texture) * * Return value: the texture target */ -GLenum +guint gst_vaapi_texture_get_target (GstVaapiTexture * texture) { - g_return_val_if_fail (texture != NULL, GL_NONE); + g_return_val_if_fail (texture != NULL, 0); - return texture->target; + return GST_VAAPI_TEXTURE_TARGET (texture); } /** @@ -372,12 +166,12 @@ gst_vaapi_texture_get_target (GstVaapiTexture * texture) * * Return value: the texture format */ -GLenum +guint gst_vaapi_texture_get_format (GstVaapiTexture * texture) { - g_return_val_if_fail (texture != NULL, GL_NONE); + g_return_val_if_fail (texture != NULL, 0); - return texture->format; + return GST_VAAPI_TEXTURE_FORMAT (texture); } /** @@ -393,7 +187,7 @@ gst_vaapi_texture_get_width (GstVaapiTexture * texture) { g_return_val_if_fail (texture != NULL, 0); - return texture->width; + return GST_VAAPI_TEXTURE_WIDTH (texture); } /** @@ -409,7 +203,7 @@ gst_vaapi_texture_get_height (GstVaapiTexture * texture) { g_return_val_if_fail (texture != NULL, 0); - return texture->height; + return GST_VAAPI_TEXTURE_HEIGHT (texture); } /** @@ -427,10 +221,10 @@ gst_vaapi_texture_get_size (GstVaapiTexture * texture, g_return_if_fail (texture != NULL); if (width_ptr) - *width_ptr = texture->width; + *width_ptr = GST_VAAPI_TEXTURE_WIDTH (texture); if (height_ptr) - *height_ptr = texture->height; + *height_ptr = GST_VAAPI_TEXTURE_HEIGHT (texture); } /** @@ -445,14 +239,19 @@ gst_vaapi_texture_get_size (GstVaapiTexture * texture, * * Return value: %TRUE on success */ -static gboolean -_gst_vaapi_texture_put_surface (GstVaapiTexture * texture, +gboolean +gst_vaapi_texture_put_surface (GstVaapiTexture * texture, GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) { - VAStatus status; + const GstVaapiTextureClass *klass; GstVaapiRectangle rect; - GLContextState old_cs; - gboolean success = FALSE; + + g_return_val_if_fail (texture != NULL, FALSE); + g_return_val_if_fail (surface != NULL, FALSE); + + klass = GST_VAAPI_TEXTURE_GET_CLASS (texture); + if (!klass) + return FALSE; if (!crop_rect) { rect.x = 0; @@ -460,83 +259,5 @@ _gst_vaapi_texture_put_surface (GstVaapiTexture * texture, gst_vaapi_surface_get_size (surface, &rect.width, &rect.height); crop_rect = ▭ } - - GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); - status = vaPutSurface (GST_VAAPI_OBJECT_VADISPLAY (texture), - GST_VAAPI_OBJECT_ID (surface), - texture->pixo->pixmap, - crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height, - 0, 0, texture->width, texture->height, - NULL, 0, from_GstVaapiSurfaceRenderFlags (flags) - ); - GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); - if (!vaapi_check_status (status, "vaPutSurface() [TFP]")) - return FALSE; - - GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); - if (texture->gl_context) { - success = gl_set_current_context (texture->gl_context, &old_cs); - if (!success) - goto end; - } - - success = gl_bind_framebuffer_object (texture->fbo); - if (!success) { - GST_DEBUG ("could not bind FBO"); - goto out_reset_context; - } - - GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); - success = gst_vaapi_surface_sync (surface); - GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); - if (!success) { - GST_DEBUG ("could not render surface to pixmap"); - goto out_unbind_fbo; - } - - success = gl_bind_pixmap_object (texture->pixo); - if (!success) { - GST_DEBUG ("could not bind GLX pixmap"); - goto out_unbind_fbo; - } - - glColor4f (1.0f, 1.0f, 1.0f, 1.0f); - glBegin (GL_QUADS); - { - glTexCoord2f (0.0f, 0.0f); - glVertex2i (0, 0); - glTexCoord2f (0.0f, 1.0f); - glVertex2i (0, texture->height); - glTexCoord2f (1.0f, 1.0f); - glVertex2i (texture->width, texture->height); - glTexCoord2f (1.0f, 0.0f); - glVertex2i (texture->width, 0); - } - glEnd (); - - success = gl_unbind_pixmap_object (texture->pixo); - if (!success) { - GST_DEBUG ("could not release GLX pixmap"); - goto out_unbind_fbo; - } - -out_unbind_fbo: - if (!gl_unbind_framebuffer_object (texture->fbo)) - success = FALSE; -out_reset_context: - if (texture->gl_context && !gl_set_current_context (&old_cs, NULL)) - success = FALSE; -end: - GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); - return success; -} - -gboolean -gst_vaapi_texture_put_surface (GstVaapiTexture * texture, - GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) -{ - g_return_val_if_fail (texture != NULL, FALSE); - g_return_val_if_fail (surface != NULL, FALSE); - - return _gst_vaapi_texture_put_surface (texture, surface, crop_rect, flags); + return klass->put_surface (texture, surface, crop_rect, flags); } diff --git a/gst-libs/gst/vaapi/gstvaapitexture.h b/gst-libs/gst/vaapi/gstvaapitexture.h index 5ae71c2..3856df8 100644 --- a/gst-libs/gst/vaapi/gstvaapitexture.h +++ b/gst-libs/gst/vaapi/gstvaapitexture.h @@ -25,23 +25,60 @@ #ifndef GST_VAAPI_TEXTURE_H #define GST_VAAPI_TEXTURE_H -#include #include -#include -#include #include G_BEGIN_DECLS -typedef struct _GstVaapiTexture GstVaapiTexture; +#define GST_VAAPI_TEXTURE(obj) \ + ((GstVaapiTexture *)(obj)) -GstVaapiTexture * -gst_vaapi_texture_new (GstVaapiDisplay * display, GLenum target, GLenum format, - guint width, guint height); +/** + * GST_VAAPI_TEXTURE_ID: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture id associated with the @texture + */ +#define GST_VAAPI_TEXTURE_ID(texture) \ + gst_vaapi_texture_get_id (GST_VAAPI_TEXTURE (texture)) -GstVaapiTexture * -gst_vaapi_texture_new_with_texture (GstVaapiDisplay * display, GLuint texture_id, - GLenum target, GLenum format); +/** + * GST_VAAPI_TEXTURE_TARGET: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture target associated with the @texture + */ +#define GST_VAAPI_TEXTURE_TARGET(texture) \ + gst_vaapi_texture_get_target (GST_VAAPI_TEXTURE (texture)) + +/** + * GST_VAAPI_TEXTURE_FORMAT: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture format associated with the @texture + */ +#define GST_VAAPI_TEXTURE_FORMAT(texture) \ + gst_vaapi_texture_get_format (GST_VAAPI_TEXTURE (texture)) + +/** + * GST_VAAPI_TEXTURE_WIDTH: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture width associated with the @texture + */ +#define GST_VAAPI_TEXTURE_WIDTH(texture) \ + gst_vaapi_texture_get_width (GST_VAAPI_TEXTURE (texture)) + +/** + * GST_VAAPI_TEXTURE_HEIGHT: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture height associated with the @texture + */ +#define GST_VAAPI_TEXTURE_HEIGHT(texture) \ + gst_vaapi_texture_get_height (GST_VAAPI_TEXTURE (texture)) + +typedef struct _GstVaapiTexture GstVaapiTexture; GstVaapiTexture * gst_vaapi_texture_ref (GstVaapiTexture * texture); @@ -53,13 +90,13 @@ void gst_vaapi_texture_replace (GstVaapiTexture ** old_texture_ptr, GstVaapiTexture * new_texture); -GLuint +guint gst_vaapi_texture_get_id (GstVaapiTexture * texture); -GLenum +guint gst_vaapi_texture_get_target (GstVaapiTexture * texture); -GLenum +guint gst_vaapi_texture_get_format (GstVaapiTexture * texture); guint diff --git a/gst-libs/gst/vaapi/gstvaapitexture_glx.c b/gst-libs/gst/vaapi/gstvaapitexture_glx.c new file mode 100644 index 0000000..acaa4f0 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapitexture_glx.c @@ -0,0 +1,383 @@ +/* + * gstvaapitexture_glx.c - VA/GLX texture abstraction + * + * Copyright (C) 2010-2011 Splitted-Desktop Systems + * Author: Gwenole Beauchesne + * Copyright (C) 2012-2014 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +/** + * SECTION:gstvaapitexture_glx + * @short_description: VA/GLX texture abstraction + */ + +#include "sysdeps.h" +#include "gstvaapitexture.h" +#include "gstvaapitexture_glx.h" +#include "gstvaapitexture_priv.h" +#include "gstvaapicompat.h" +#include "gstvaapiutils.h" +#include "gstvaapiutils_glx.h" +#include "gstvaapidisplay_glx.h" +#include "gstvaapidisplay_x11_priv.h" +#include "gstvaapidisplay_glx_priv.h" + +#define DEBUG 1 +#include "gstvaapidebug.h" + +#define GST_VAAPI_TEXTURE_GLX(texture) \ + ((GstVaapiTextureGLX *)(texture)) + +typedef struct _GstVaapiTextureGLX GstVaapiTextureGLX; +typedef struct _GstVaapiTextureGLXClass GstVaapiTextureGLXClass; + +/** + * GstVaapiTextureGLX: + * + * Base object for GLX texture wrapper. + */ +struct _GstVaapiTextureGLX +{ + /*< private >*/ + GstVaapiTexture parent_instance; + + GLContextState *gl_context; + GLPixmapObject *pixo; + GLFramebufferObject *fbo; +}; + +/** + * GstVaapiTextureGLXClass: + * + * Base class for GLX texture wrapper. + */ +struct _GstVaapiTextureGLXClass +{ + /*< private >*/ + GstVaapiTextureClass parent_class; +}; + +static gboolean +gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture, + GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, + guint flags); + +static void +destroy_objects (GstVaapiTextureGLX * texture) +{ + GLContextState old_cs; + + if (texture->gl_context) + gl_set_current_context (texture->gl_context, &old_cs); + + if (texture->fbo) { + gl_destroy_framebuffer_object (texture->fbo); + texture->fbo = NULL; + } + + if (texture->pixo) { + gl_destroy_pixmap_object (texture->pixo); + texture->pixo = NULL; + } + + if (texture->gl_context) { + gl_set_current_context (&old_cs, NULL); + gl_destroy_context (texture->gl_context); + texture->gl_context = NULL; + } +} + +static void +destroy_texture_unlocked (GstVaapiTexture * texture) +{ + const guint texture_id = GST_VAAPI_TEXTURE_ID (texture); + + destroy_objects (GST_VAAPI_TEXTURE_GLX (texture)); + + if (texture_id) { + if (!texture->is_wrapped) + glDeleteTextures (1, &texture_id); + GST_VAAPI_TEXTURE_ID (texture) = 0; + } +} + +static void +gst_vaapi_texture_glx_destroy (GstVaapiTexture * texture) +{ + GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); + destroy_texture_unlocked (texture); + GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); +} + +static gboolean +create_objects (GstVaapiTextureGLX * texture, guint texture_id) +{ + GstVaapiTexture *const base_texture = GST_VAAPI_TEXTURE (texture); + GLContextState old_cs; + gboolean success = FALSE; + + gl_get_current_context (&old_cs); + + texture->gl_context = gl_create_context (GST_VAAPI_OBJECT_XDISPLAY (texture), + GST_VAAPI_OBJECT_XSCREEN (texture), &old_cs); + if (!texture->gl_context || + !gl_set_current_context (texture->gl_context, NULL)) + return FALSE; + + texture->pixo = gl_create_pixmap_object (GST_VAAPI_OBJECT_XDISPLAY (texture), + base_texture->width, base_texture->height); + if (!texture->pixo) { + GST_ERROR ("failed to create GLX pixmap"); + goto out_reset_context; + } + + texture->fbo = gl_create_framebuffer_object (base_texture->gl_target, + texture_id, base_texture->width, base_texture->height); + if (!texture->fbo) { + GST_ERROR ("failed to create FBO"); + goto out_reset_context; + } + success = TRUE; + +out_reset_context: + gl_set_current_context (&old_cs, NULL); + return success; +} + +static gboolean +create_texture_unlocked (GstVaapiTexture * texture) +{ + guint texture_id; + + if (texture->is_wrapped) + texture_id = GST_VAAPI_TEXTURE_ID (texture); + else { + texture_id = gl_create_texture (texture->gl_target, texture->gl_format, + texture->width, texture->height); + if (!texture_id) + return FALSE; + GST_VAAPI_TEXTURE_ID (texture) = texture_id; + } + return create_objects (GST_VAAPI_TEXTURE_GLX (texture), texture_id); +} + +static gboolean +gst_vaapi_texture_glx_create (GstVaapiTexture * texture) +{ + gboolean success; + + GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); + success = create_texture_unlocked (texture); + GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); + return success; +} + +static void +gst_vaapi_texture_glx_class_init (GstVaapiTextureGLXClass * klass) +{ + GstVaapiObjectClass *const object_class = GST_VAAPI_OBJECT_CLASS (klass); + GstVaapiTextureClass *const texture_class = GST_VAAPI_TEXTURE_CLASS (klass); + + object_class->finalize = (GstVaapiObjectFinalizeFunc) + gst_vaapi_texture_glx_destroy; + + texture_class->allocate = gst_vaapi_texture_glx_create; + texture_class->put_surface = gst_vaapi_texture_glx_put_surface; +} + +#define gst_vaapi_texture_glx_finalize gst_vaapi_texture_glx_destroy +GST_VAAPI_OBJECT_DEFINE_CLASS_WITH_CODE (GstVaapiTextureGLX, + gst_vaapi_texture_glx, gst_vaapi_texture_glx_class_init (&g_class)); + +/** + * gst_vaapi_texture_glx_new: + * @display: a #GstVaapiDisplay + * @target: the target to which the texture is bound + * @format: the format of the pixel data + * @width: the requested width, in pixels + * @height: the requested height, in pixels + * + * Creates a texture with the specified dimensions, @target and + * @format. Note that only GL_TEXTURE_2D @target and GL_RGBA or + * GL_BGRA formats are supported at this time. + * + * The application shall maintain the live GL context itself. That is, + * gst_vaapi_window_glx_make_current() must be called beforehand, or + * any other function like glXMakeCurrent() if the context is managed + * outside of this library. + * + * Return value: the newly created #GstVaapiTexture object + */ +GstVaapiTexture * +gst_vaapi_texture_glx_new (GstVaapiDisplay * display, guint target, + guint format, guint width, guint height) +{ + g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); + + return + gst_vaapi_texture_new (GST_VAAPI_TEXTURE_CLASS + (gst_vaapi_texture_glx_class ()), display, GL_NONE, target, format, width, + height); +} + +/** + * gst_vaapi_texture_glx_new_wrapped: + * @display: a #GstVaapiDisplay + * @texture_id: the foreign GL texture name to use + * @target: the target to which the texture is bound + * @format: the format of the pixel data + * + * Creates a texture from an existing GL texture, with the specified + * @target and @format. Note that only GL_TEXTURE_2D @target and + * GL_RGBA or GL_BGRA formats are supported at this time. The + * dimensions will be retrieved from the @texture_id. + * + * The application shall maintain the live GL context itself. That is, + * gst_vaapi_window_glx_make_current() must be called beforehand, or + * any other function like glXMakeCurrent() if the context is managed + * outside of this library. + * + * Return value: the newly created #GstVaapiTexture object + */ +GstVaapiTexture * +gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display, + guint texture_id, guint target, guint format) +{ + guint width, height, border_width; + GLTextureState ts; + gboolean success; + + g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); + g_return_val_if_fail (target != GL_NONE, NULL); + g_return_val_if_fail (format != GL_NONE, NULL); + + /* Check texture dimensions */ + GST_VAAPI_DISPLAY_LOCK (display); + success = gl_bind_texture (&ts, target, texture_id); + if (success) { + if (!gl_get_texture_param (target, GL_TEXTURE_WIDTH, &width) || + !gl_get_texture_param (target, GL_TEXTURE_HEIGHT, &height) || + !gl_get_texture_param (target, GL_TEXTURE_BORDER, &border_width)) + success = FALSE; + gl_unbind_texture (&ts); + } + GST_VAAPI_DISPLAY_UNLOCK (display); + if (!success) + return NULL; + + width -= 2 * border_width; + height -= 2 * border_width; + g_return_val_if_fail (width > 0, NULL); + g_return_val_if_fail (height > 0, NULL); + + return + gst_vaapi_texture_new (GST_VAAPI_TEXTURE_CLASS + (gst_vaapi_texture_glx_class ()), display, texture_id, target, format, + width, height); +} + +/** + * gst_vaapi_texture_put_surface: + * @texture: a #GstVaapiTexture + * @surface: a #GstVaapiSurface + * @flags: postprocessing flags. See #GstVaapiTextureRenderFlags + * + * Renders the @surface into the àtexture. The @flags specify how + * de-interlacing (if needed), color space conversion, scaling and + * other postprocessing transformations are performed. + * + * Return value: %TRUE on success + */ +static gboolean +gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * base_texture, + GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) +{ + GstVaapiTextureGLX *const texture = GST_VAAPI_TEXTURE_GLX (base_texture); + VAStatus status; + GLContextState old_cs; + gboolean success = FALSE; + + status = vaPutSurface (GST_VAAPI_OBJECT_VADISPLAY (texture), + GST_VAAPI_OBJECT_ID (surface), texture->pixo->pixmap, + crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height, + 0, 0, base_texture->width, base_texture->height, + NULL, 0, from_GstVaapiSurfaceRenderFlags (flags)); + if (!vaapi_check_status (status, "vaPutSurface() [TFP]")) + return FALSE; + + if (texture->gl_context && + !gl_set_current_context (texture->gl_context, &old_cs)) + return FALSE; + + if (!gl_bind_framebuffer_object (texture->fbo)) { + GST_ERROR ("failed to bind FBO"); + goto out_reset_context; + } + + if (!gst_vaapi_surface_sync (surface)) { + GST_ERROR ("failed to render surface to pixmap"); + goto out_unbind_fbo; + } + + if (!gl_bind_pixmap_object (texture->pixo)) { + GST_ERROR ("could not bind GLX pixmap"); + goto out_unbind_fbo; + } + + glColor4f (1.0f, 1.0f, 1.0f, 1.0f); + glBegin (GL_QUADS); + { + glTexCoord2f (0.0f, 0.0f); + glVertex2i (0, 0); + glTexCoord2f (0.0f, 1.0f); + glVertex2i (0, base_texture->height); + glTexCoord2f (1.0f, 1.0f); + glVertex2i (base_texture->width, base_texture->height); + glTexCoord2f (1.0f, 0.0f); + glVertex2i (base_texture->width, 0); + } + glEnd (); + + if (!gl_unbind_pixmap_object (texture->pixo)) { + GST_ERROR ("failed to release GLX pixmap"); + goto out_unbind_fbo; + } + success = TRUE; + +out_unbind_fbo: + if (!gl_unbind_framebuffer_object (texture->fbo)) + success = FALSE; +out_reset_context: + if (texture->gl_context && !gl_set_current_context (&old_cs, NULL)) + success = FALSE; + return success; +} + +static gboolean +gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture, + GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) +{ + gboolean success; + + GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); + success = gst_vaapi_texture_glx_put_surface_unlocked (texture, surface, + crop_rect, flags); + GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); + return success; +} diff --git a/gst-libs/gst/vaapi/gstvaapitexture_glx.h b/gst-libs/gst/vaapi/gstvaapitexture_glx.h new file mode 100644 index 0000000..db8ddbb --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapitexture_glx.h @@ -0,0 +1,42 @@ +/* + * gstvaapitexture_glx.h - VA/GLX texture abstraction + * + * Copyright (C) 2010-2011 Splitted-Desktop Systems + * Author: Gwenole Beauchesne + * Copyright (C) 2012-2014 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_TEXTURE_GLX_H +#define GST_VAAPI_TEXTURE_GLX_H + +#include + +G_BEGIN_DECLS + +GstVaapiTexture * +gst_vaapi_texture_glx_new (GstVaapiDisplay * display, guint target, + guint format, guint width, guint height); + +GstVaapiTexture * +gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display, guint id, + guint target, guint format); + +G_END_DECLS + +#endif /* GST_VAAPI_TEXTURE_GLX_H */ diff --git a/gst-libs/gst/vaapi/gstvaapitexture_priv.h b/gst-libs/gst/vaapi/gstvaapitexture_priv.h new file mode 100644 index 0000000..8cf57e6 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapitexture_priv.h @@ -0,0 +1,160 @@ +/* + * gstvaapitexture_priv.h - VA texture abstraction (private definitions) + * + * Copyright (C) 2010-2011 Splitted-Desktop Systems + * Author: Gwenole Beauchesne + * Copyright (C) 2012-2014 Intel Corporation + * Author: Gwenole Beauchesne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_TEXTURE_PRIV_H +#define GST_VAAPI_TEXTURE_PRIV_H + +#include "gstvaapiobject_priv.h" + +G_BEGIN_DECLS + +#define GST_VAAPI_TEXTURE_CLASS(klass) \ + ((GstVaapiTextureClass *)(klass)) + +#define GST_VAAPI_TEXTURE_GET_CLASS(obj) \ + GST_VAAPI_TEXTURE_CLASS (GST_VAAPI_OBJECT_GET_CLASS (obj)) + +/** + * GST_VAAPI_TEXTURE_ID: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture id associated with the @texture + */ +#undef GST_VAAPI_TEXTURE_ID +#define GST_VAAPI_TEXTURE_ID(texture) \ + (GST_VAAPI_OBJECT_ID (texture)) + +/** + * GST_VAAPI_TEXTURE_TARGET: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture target associated with the @texture + */ +#undef GST_VAAPI_TEXTURE_TARGET +#define GST_VAAPI_TEXTURE_TARGET(texture) \ + (GST_VAAPI_TEXTURE (texture)->gl_target) + +/** + * GST_VAAPI_TEXTURE_FORMAT: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture format associated with the @texture + */ +#undef GST_VAAPI_TEXTURE_FORMAT +#define GST_VAAPI_TEXTURE_FORMAT(texture) \ + (GST_VAAPI_TEXTURE (texture)->gl_format) + +/** + * GST_VAAPI_TEXTURE_WIDTH: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture width associated with the @texture + */ +#undef GST_VAAPI_TEXTURE_WIDTH +#define GST_VAAPI_TEXTURE_WIDTH(texture) \ + (GST_VAAPI_TEXTURE (texture)->width) + +/** + * GST_VAAPI_TEXTURE_HEIGHT: + * @texture: a #GstVaapiTexture + * + * Macro that evaluates to the GL texture height associated with the @texture + */ +#undef GST_VAAPI_TEXTURE_HEIGHT +#define GST_VAAPI_TEXTURE_HEIGHT(texture) \ + (GST_VAAPI_TEXTURE (texture)->height) + +/* GstVaapiTextureClass hooks */ +typedef gboolean (*GstVaapiTextureAllocateFunc) (GstVaapiTexture * texture); +typedef gboolean (*GstVaapiTexturePutSurfaceFunc) (GstVaapiTexture * texture, + GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, + guint flags); + +typedef struct _GstVaapiTextureClass GstVaapiTextureClass; + +/** + * GstVaapiTexture: + * + * Base class for API-dependent textures. + */ +struct _GstVaapiTexture { + /*< private >*/ + GstVaapiObject parent_instance; + + /*< protected >*/ + guint gl_target; + guint gl_format; + guint width; + guint height; + guint is_wrapped:1; +}; + +/** + * GstVaapiTextureClass: + * @put_surface: virtual function to render a #GstVaapiSurface into a texture + * + * Base class for API-dependent textures. + */ +struct _GstVaapiTextureClass { + /*< private >*/ + GstVaapiObjectClass parent_class; + + /*< protected >*/ + GstVaapiTextureAllocateFunc allocate; + GstVaapiTexturePutSurfaceFunc put_surface; +}; + +GstVaapiTexture * +gst_vaapi_texture_new (const GstVaapiTextureClass * klass, + GstVaapiDisplay * display, guint texture_id, guint target, guint format, + guint width, guint height); + +/* Inline reference counting for core libgstvaapi library */ +#ifdef IN_LIBGSTVAAPI_CORE +#define gst_vaapi_texture_ref_internal(texture) \ + ((gpointer)gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (texture))) + +#define gst_vaapi_texture_unref_internal(texture) \ + gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (texture)) + +#define gst_vaapi_texture_replace_internal(old_texture_ptr, new_texture) \ + gst_vaapi_mini_object_replace ((GstVaapiMiniObject **)(old_texture_ptr), \ + GST_VAAPI_MINI_OBJECT (new_texture)) + +#undef gst_vaapi_texture_ref +#define gst_vaapi_texture_ref(texture) \ + gst_vaapi_texture_ref_internal ((texture)) + +#undef gst_vaapi_texture_unref +#define gst_vaapi_texture_unref(texture) \ + gst_vaapi_texture_unref_internal ((texture)) + +#undef gst_vaapi_texture_replace +#define gst_vaapi_texture_replace(old_texture_ptr, new_texture) \ + gst_vaapi_texture_replace_internal ((old_texture_ptr), (new_texture)) +#endif + +G_END_DECLS + +#endif /* GST_VAAPI_TEXTURE_PRIV_H */ diff --git a/gst/vaapi/gstvaapivideoconverter_glx.c b/gst/vaapi/gstvaapivideoconverter_glx.c index 06ca7c5..4512d17 100644 --- a/gst/vaapi/gstvaapivideoconverter_glx.c +++ b/gst/vaapi/gstvaapivideoconverter_glx.c @@ -23,7 +23,7 @@ */ #include "gst/vaapi/sysdeps.h" -#include +#include #include "gstvaapivideoconverter_glx.h" #include "gstvaapivideoconverter_x11.h" #include "gstvaapipluginutil.h" @@ -120,7 +120,7 @@ gst_vaapi_video_converter_glx_new (GstBuffer * buffer, const gchar * type, /* FIXME Should we assume target and format ? */ texture = - gst_vaapi_texture_new_with_texture (gst_vaapi_video_meta_get_display + gst_vaapi_texture_glx_new_wrapped (gst_vaapi_video_meta_get_display (meta), g_value_get_uint (dest), GL_TEXTURE_2D, GL_BGRA); if (!texture) return NULL; @@ -149,7 +149,7 @@ gst_vaapi_video_converter_glx_upload (GstSurfaceConverter * self, const guint texture = gst_vaapi_texture_get_id (priv->texture); gst_vaapi_texture_replace (&priv->texture, NULL); - priv->texture = gst_vaapi_texture_new_with_texture (new_dpy, + priv->texture = gst_vaapi_texture_glx_new_wrapped (new_dpy, texture, GL_TEXTURE_2D, GL_BGRA); } diff --git a/gst/vaapi/gstvaapivideometa_texture.c b/gst/vaapi/gstvaapivideometa_texture.c index 429a8b3..6b08f94 100644 --- a/gst/vaapi/gstvaapivideometa_texture.c +++ b/gst/vaapi/gstvaapivideometa_texture.c @@ -25,9 +25,14 @@ */ #include "gst/vaapi/sysdeps.h" +#include #include "gstvaapivideometa.h" #include "gstvaapipluginutil.h" +#if USE_GLX +#include +#endif + #if GST_CHECK_VERSION(1,1,0) && USE_GLX #include "gstvaapivideometa_texture.h" @@ -95,7 +100,7 @@ gst_vaapi_texture_upload (GstVideoGLTextureUploadMeta * meta, gst_vaapi_texture_get_id (meta_texture->texture) != texture_id[0]) { /* FIXME: should we assume target? */ GstVaapiTexture *const texture = - gst_vaapi_texture_new_with_texture (dpy, texture_id[0], + gst_vaapi_texture_glx_new_wrapped (dpy, texture_id[0], GL_TEXTURE_2D, GL_RGBA); gst_vaapi_texture_replace (&meta_texture->texture, texture); if (!texture) diff --git a/tests/test-textures.c b/tests/test-textures.c index c4673ad..63b4c78 100644 --- a/tests/test-textures.c +++ b/tests/test-textures.c @@ -23,9 +23,9 @@ #include "gst/vaapi/sysdeps.h" #include #include +#include #include #include -#include #include "image.h" static inline void pause(void) @@ -89,10 +89,10 @@ main(int argc, char *argv[]) g_error("coult not bind GL context"); g_print("#\n"); - g_print("# Create texture with gst_vaapi_texture_new()\n"); + g_print("# Create texture with gst_vaapi_texture_glx_new()\n"); g_print("#\n"); { - texture = gst_vaapi_texture_new( + texture = gst_vaapi_texture_glx_new( display, GL_TEXTURE_2D, GL_RGBA, @@ -113,7 +113,7 @@ main(int argc, char *argv[]) } g_print("#\n"); - g_print("# Create texture with gst_vaapi_texture_new_with_texture()\n"); + g_print("# Create texture with gst_vaapi_texture_glx_new_wrapped()\n"); g_print("#\n"); { const GLenum target = GL_TEXTURE_2D; @@ -139,7 +139,7 @@ main(int argc, char *argv[]) ); glDisable(target); - texture = gst_vaapi_texture_new_with_texture( + texture = gst_vaapi_texture_glx_new_wrapped( display, texture_id, target, @@ -152,7 +152,7 @@ main(int argc, char *argv[]) g_error("invalid texture id"); if (gl_get_current_texture_2d() != texture_id) - g_error("gst_vaapi_texture_new_with_texture() altered texture bindings"); + g_error("gst_vaapi_texture_glx_new_wrapped() altered texture bindings"); textures[1] = texture;